Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

contracts: add curve25519 pk precompile #116

Merged
merged 1 commit into from
Feb 22, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 40 additions & 11 deletions contracts/contracts/Sapphire.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@ library Sapphire {
0x0100000000000000000000000000000000000003;
address private constant DECRYPT =
0x0100000000000000000000000000000000000004;
address private constant GENERATE_KEYPAIR =
address private constant GENERAGE_SIGNING_KEYPAIR =
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be GENERATE_SIGNING_KEYPAIR

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed! Can you open up a PR with the fix? Thanks a lot!

0x0100000000000000000000000000000000000005;
address private constant SIGN_DIGEST =
0x0100000000000000000000000000000000000006;
address private constant VERIFY_DIGEST =
0x0100000000000000000000000000000000000007;
address private constant CURVE25519_PUBLIC_KEY =
0x0100000000000000000000000000000000000008;

type Curve25519PublicKey is bytes32;
type Curve25519SecretKey is bytes32;

enum SigningAlg {
// Ed25519 signature over the provided message using SHA-512/265 with a domain separator.
Expand Down Expand Up @@ -59,17 +64,42 @@ library Sapphire {
return entropy;
}

/**
* @dev Generates a Curve25519 keypair.
* @param pers An optional personalization string used to add domain separation.
* @return pk The Curve25519 public key. Useful for key exchange.
* @return sk The Curve25519 secret key. Pairs well with {`deriveSymmetricKey`}.
*/
function generateCurve25519KeyPair(bytes memory pers)
internal
view
returns (Curve25519PublicKey pk, Curve25519SecretKey sk)
{
bytes memory scalar = randomBytes(32, pers);
// Twiddle some bits, as per RFC 7748 §5.
scalar[0] &= 0xf8; // Make it a multiple of 8 to avoid small subgroup attacks.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, thanks! Can you open up a PR with the proposed fix (removing the scalar clamp)?

scalar[31] &= 0x7f; // Clamp to < 2^255 - 19
scalar[31] |= 0x40; // Clamp to >= 2^254
(bool success, bytes memory pkBytes) = CURVE25519_PUBLIC_KEY.staticcall(
scalar
);
require(success, "gen curve25519 pk: failed");
return (
Curve25519PublicKey.wrap(bytes32(pkBytes)),
Curve25519SecretKey.wrap(bytes32(scalar))
);
}

/**
* @dev Derive a symmetric key from a pair of keys using x25519.
* @param peerPublicKey The peer's public key.
* @param secretKey Your secret key.
* @return A derived symmetric key.
*/
function deriveSymmetricKey(bytes32 peerPublicKey, bytes32 secretKey)
internal
view
returns (bytes32)
{
function deriveSymmetricKey(
Curve25519PublicKey peerPublicKey,
Curve25519SecretKey secretKey
) internal view returns (bytes32) {
(bool success, bytes memory symmetric) = DERIVE_KEY.staticcall(
abi.encode(peerPublicKey, secretKey)
);
Expand Down Expand Up @@ -126,15 +156,14 @@ library Sapphire {
* @return publicKey The public half of the keypair.
* @return secretKey The secret half of the keypair.
*/
function generateKeyPair(SigningAlg alg, bytes memory seed)
function generateSigningKeyPair(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");
(bool success, bytes memory keypair) = GENERAGE_SIGNING_KEYPAIR
.staticcall(abi.encode(alg, seed));
require(success, "gen signing keypair: failed");
return abi.decode(keypair, (bytes, bytes));
}

Expand Down