Skip to content

Commit

Permalink
Add wrappers for signature precompiles to Sapphire library (#80)
Browse files Browse the repository at this point in the history
Co-authored-by: Nick Hynes <nhynes@oasislabs.com>
  • Loading branch information
jberci and nhynes committed Jan 18, 2023
1 parent 47b79b2 commit 8f40c63
Show file tree
Hide file tree
Showing 6 changed files with 3,558 additions and 10,089 deletions.
1 change: 1 addition & 0 deletions contracts/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
typechain-types/
85 changes: 85 additions & 0 deletions contracts/contracts/Sapphire.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,32 @@ library Sapphire {
0x0100000000000000000000000000000000000003;
address private constant DECRYPT =
0x0100000000000000000000000000000000000004;
address private constant GENERATE_KEYPAIR =
0x0100000000000000000000000000000000000005;
address private constant SIGN_DIGEST =
0x0100000000000000000000000000000000000006;
address private constant VERIFY_DIGEST =
0x0100000000000000000000000000000000000007;

enum SigningAlg {
// Ed25519 signature over the provided message using SHA-512/265 with a domain separator.
// Can be used to sign transactions for the Oasis consensus layer and SDK paratimes.
Ed25519Oasis,
// Ed25519 signature over the provided message.
Ed25519Pure,
// Ed25519 signature over the provided prehashed SHA-512 digest.
Ed25519PrehashedSha512,
// Secp256k1 signature over the provided message using SHA-512/256 with a domain separator.
// Can be used to sign transactions for the Oasis consensus layer and SDK paratimes.
Secp256k1Oasis,
// Secp256k1 over the provided Keccak256 digest.
// Can be used to sign transactions for Ethereum-compatible networks.
Secp256k1PrehashedKeccak256,
// Secp256k1 signature over the provided SHA-256 digest.
Secp256k1PrehashedSha256,
// Sr25519 signature over the provided message.
Sr25519
}

/**
* @dev Returns cryptographically secure random bytes.
Expand Down Expand Up @@ -92,4 +118,63 @@ library Sapphire {
require(success, "decrypt: failed");
return plaintext;
}

/**
* @dev Generate a public/private key pair using the specified method and seed.
* @param alg The signing alg for which to generate a keypair.
* @param seed The seed to use for generating the key pair. You can use the `randomBytes` method if you don't already have a seed.
* @return publicKey The public half of the keypair.
* @return secretKey The secret half of the keypair.
*/
function generateKeyPair(SigningAlg alg, bytes memory seed)
internal
view
returns (bytes memory publicKey, bytes memory secretKey)
{
(bool success, bytes memory keypair) = GENERATE_KEYPAIR.staticcall(
abi.encode(alg, seed)
);
require(success, "generateKeyPair: failed");
return abi.decode(keypair, (bytes, bytes));
}

/**
* @dev Sign a message within the provided context using the specified algorithm, and return the signature.
* @param alg The signing algorithm to use.
* @param secretKey The secret key to use for signing. The key must be valid for use with the requested algorithm.
* @param digest The hash of the message to sign.
* @return signature The resulting signature.
*/
function signDigest(
uint256 alg,
bytes memory secretKey,
bytes memory digest
) internal view returns (bytes memory signature) {
(bool success, bytes memory sig) = SIGN_DIGEST.staticcall(
abi.encode(alg, secretKey, digest)
);
require(success, "signDigest: failed");
return sig;
}

/**
* @dev Verifies that the provided digest was signed with using the secret key corresponding to the provided private key and the specified signing algorithm.
* @param alg The signing algorithm by which the signature was generated.
* @param publicKey The public key against which to check the signature.
* @param digest The hash of the message that was signed.
* @param signature The signature to check.
* @return verified Whether the signature is valid for the given parameters.
*/
function verifyDigestSignature(
SigningAlg alg,
bytes memory publicKey,
bytes memory digest,
bytes memory signature
) internal view returns (bool verified) {
(bool success, bytes memory v) = VERIFY_DIGEST.staticcall(
abi.encode(alg, publicKey, digest, signature)
);
require(success, "verifyDigestSignature: failed");
return abi.decode(v, (bool));
}
}
Loading

0 comments on commit 8f40c63

Please sign in to comment.