-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
contracts: implement SHA512-256 as it's used throughout the Oasis eco…
…system
- Loading branch information
Showing
3 changed files
with
98 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import {sha512_256} from "./Sapphire.sol"; | ||
|
||
// Note that the SHA512_256 block size is 128 bytes, while the output is 32 bytes | ||
uint256 constant SHA512_256_BLOCK_SIZE = 128; | ||
|
||
// We don't (yet) have the MCOPY opcode, so use the IDENTITY precompile | ||
uint256 constant PRECOMPILE_IDENTITY_ADDRESS = 0x4; | ||
|
||
// HMAC block-sized inner padding | ||
bytes32 constant HMAC_IPAD = 0x3636363636363636363636363636363636363636363636363636363636363636; | ||
|
||
// OPAD ^ IPAD, (OPAD = 0x5c) | ||
bytes32 constant HMAC_OPAD_XOR_IPAD = 0x6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a; | ||
|
||
/** | ||
* @notice Implements HMAC using SHA512-256. | ||
* @dev https://en.wikipedia.org/wiki/HMAC | ||
* @param key the secret key. | ||
* @param message the message to be authenticated. | ||
* | ||
* #### Example | ||
* | ||
* ```solidity | ||
* bytes memory key = "arbitrary length key"; | ||
* bytes memory message = "arbitrary length message"; | ||
* bytes32 hmac = HMAC_sha512_256(key, message) | ||
* ``` | ||
*/ | ||
function HMAC_sha512_256(bytes memory key, bytes memory message) | ||
view | ||
returns (bytes32) | ||
{ | ||
bytes32[4] memory buf; | ||
|
||
if (key.length > SHA512_256_BLOCK_SIZE) { | ||
buf[0] = sha512_256(key); | ||
} else { | ||
bool success; | ||
|
||
assembly { | ||
let size := mload(key) | ||
success := staticcall( | ||
gas(), | ||
PRECOMPILE_IDENTITY_ADDRESS, | ||
add(32, key), // Skip uint256 length prefix of key bytes | ||
size, | ||
buf, | ||
size | ||
) | ||
} | ||
|
||
require(success, "memcpy"); | ||
} | ||
|
||
for (uint256 i = 0; i < buf.length; i++) { | ||
buf[i] ^= HMAC_IPAD; | ||
} | ||
|
||
bytes32 ihash = sha512_256(abi.encodePacked(buf, message)); | ||
|
||
for (uint256 i = 0; i < buf.length; i++) { | ||
buf[i] ^= HMAC_OPAD_XOR_IPAD; | ||
} | ||
|
||
return sha512_256(abi.encodePacked(buf, ihash)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters