Skip to content

Commit

Permalink
Expose secp256k1 and keccak256 in the SDK (#1028)
Browse files Browse the repository at this point in the history
### What

Expose `secp256k1` and `keccak256` in the SDK.

### Why

`secp256k1` is a widely used cryptographic signature algorithm and
`keccak256` is a widely used hashing algorithm. Exposing these functions
will allow smart contract developers to utilize these algorithms in
their applications without having to implement them themselves.

### Follow on work

* ~Pending [this
discussion](#1023 (comment))
on best practices I will call `check_env` where applicable.~


### Known limitations

N/A
------
**Github Issue**: [surface new crypto functions in
SDK](#970)

---------

Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com>
  • Loading branch information
masonforest and leighmcculloch authored Sep 18, 2023
1 parent 4efef11 commit b5cc44a
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 0 deletions.
29 changes: 29 additions & 0 deletions soroban-sdk/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ impl Crypto {
unsafe { BytesN::unchecked_new(env.clone(), bin) }
}

/// Returns the Keccak-256 hash of the data.
pub fn keccak256(&self, data: &Bytes) -> BytesN<32> {
let env = self.env();
let bin = internal::Env::compute_hash_keccak256(env, data.into()).unwrap_infallible();
unsafe { BytesN::unchecked_new(env.clone(), bin) }
}

/// Verifies an ed25519 signature.
///
/// The signature is verified as a valid signature of the message by the
Expand All @@ -39,4 +46,26 @@ impl Crypto {
signature.to_object(),
);
}

/// Recovers the ECDSA secp256k1 public key.
///
/// The public key returned is the SEC-1-encoded ECDSA secp256k1 public key
/// that produced the 64-byte signature over a given 32-byte message digest,
/// for a given recovery_id byte.
pub fn secp256k1_recover(
&self,
message_digest: &BytesN<32>,
signature: &BytesN<64>,
recorvery_id: u32,
) -> BytesN<65> {
let env = self.env();
let bytes = internal::Env::recover_key_ecdsa_secp256k1(
env,
message_digest.to_object(),
signature.to_object(),
recorvery_id.into(),
)
.unwrap_infallible();
unsafe { BytesN::unchecked_new(env.clone(), bytes) }
}
}
2 changes: 2 additions & 0 deletions soroban-sdk/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ mod contract_udt_struct_tuple;
mod contractimport;
mod contractimport_with_error;
mod crypto_ed25519;
mod crypto_keccak256;
mod crypto_secp256k1;
mod crypto_sha256;
mod env;
mod prng;
Expand Down
13 changes: 13 additions & 0 deletions soroban-sdk/src/tests/crypto_keccak256.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use crate::{bytesn, Env, IntoVal};

#[test]
fn test_keccak256() {
let env = Env::default();

let bytes = b"test vector for soroban".into_val(&env);
let expect = bytesn!(
&env,
0x352fe2eaddf44eb02eb3eab1f8d6ff4ba426df4f1734b1e3f210d621ee8853d9
);
assert_eq!(env.crypto().keccak256(&bytes), expect);
}
26 changes: 26 additions & 0 deletions soroban-sdk/src/tests/crypto_secp256k1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use crate::{bytesn, Env};

#[test]
fn test_recover_key_ecdsa_secp256k1() {
let env = Env::default();

// From: https://github.com/ethereum/go-ethereum/blob/90d5bd85bcf2919ac2735a47fde675213348a0a6/crypto/secp256k1/secp256_test.go#L204-L217
let message_digest = bytesn!(
&env,
0xce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008
);
let signature = bytesn!(
&env,
0x90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93
);
let recovery_id = 1;
let expected_public_key = bytesn!(
&env,
0x04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652
);
assert_eq!(
env.crypto()
.secp256k1_recover(&message_digest, &signature, recovery_id),
expected_public_key
);
}

0 comments on commit b5cc44a

Please sign in to comment.