Skip to content

Commit

Permalink
Declare Ed25519Signature and use it with Ed25519PrivateKey and Public…
Browse files Browse the repository at this point in the history
…Key, and same for Secp256k1.
  • Loading branch information
Sajjon committed Feb 19, 2024
1 parent 9437497 commit 5f5cc20
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 69 deletions.
8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ path = "src/bin.rs"
[dependencies]
log = "0.4.20"
pretty_env_logger = "0.5.0"
derive_more = { version = "1.0.0-beta.6", features = ["debug", "display"] }
derive_more = { version = "1.0.0-beta.6", features = [
"debug",
"display",
"from_str",
] }
serde = { version = "1.0.193", features = ["derive", "rc", "std"] }
serde_json = { version = "1.0.108", features = ["preserve_order"] }
serde_with = { version = "3.4.0" }
Expand All @@ -46,7 +50,7 @@ radix-engine-interface = { git = "https://github.com/radixdlt/radixdlt-scrypto",
radix-engine-toolkit-json = { git = "https://github.com/radixdlt/radix-engine-toolkit", rev = "9dc3deeb3299b4f4c255f36bb3d504681379ad5a" }
radix-engine-toolkit = { git = "https://github.com/radixdlt/radix-engine-toolkit", rev = "9dc3deeb3299b4f4c255f36bb3d504681379ad5a" }
enum-iterator = "1.4.1"
bip32 = "0.5.1" # only need Secp256k1, to do validation of PublicKey
bip32 = "0.5.1" # only need Secp256k1, to do validation of PublicKey
ed25519-dalek = "1.0.1"
rand = "0.8.5"
hex = "0.4.3"
Expand Down
7 changes: 5 additions & 2 deletions src/core/types/decimal192.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,11 @@ impl FromStr for InnerDecimal {
)]
#[display("{}", self.native())]
pub struct Decimal192 {
/// @Kotlin / Swift developer: Do not use this property/field. Instead use all the provided
/// methods on the `Decimal` type.
/// @Kotlin / Swift developer: Do NOT use this property/field. Instead use all the provided methods on the `Decimal192` type.
/// (which are in fact vendored as freestanding global functions,
/// due to limitations in UniFII as of Feb 2024, but you should
/// create extension methods on Decimal192 in FFI land, translating
/// these functions into methods.)
__inner: InnerDecimal, // Strange field name to try as much as possible hide it in FFI land.
}

Expand Down
21 changes: 13 additions & 8 deletions src/core/types/keys/ed25519/private_key.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::prelude::*;

use radix_engine_common::crypto::{
Ed25519PrivateKey as ScryptoEd25519PrivateKey,
Ed25519Signature as ScryptoEd25519Signature, IsHash,
Ed25519PrivateKey as ScryptoEd25519PrivateKey, IsHash,
};

/// An Ed25519 private key used to create cryptographic signatures, using
Expand Down Expand Up @@ -35,16 +34,16 @@ impl IsPrivateKey<Ed25519PublicKey> for Ed25519PrivateKey {
SLIP10Curve::Curve25519
}

type Signature = ScryptoEd25519Signature;
type Signature = Ed25519Signature;

fn public_key(&self) -> Ed25519PublicKey {
self.0.public_key().try_into().expect(
"Public Key from EC scalar multiplication should always be valid.",
)
}

fn sign(&self, msg_hash: &impl IsHash) -> ScryptoEd25519Signature {
self.0.sign(msg_hash)
fn sign(&self, msg_hash: &impl IsHash) -> Self::Signature {
self.0.sign(msg_hash).into()
}
}

Expand Down Expand Up @@ -111,6 +110,8 @@ impl HasPlaceholder for Ed25519PrivateKey {
}

impl Ed25519PrivateKey {
/// A placeholder used to facilitate unit tests.
///
/// `833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42`
///
/// expected public key:
Expand All @@ -124,8 +125,10 @@ impl Ed25519PrivateKey {
.unwrap()
}

/// A placeholder used to facilitate unit tests.
///
/// `1498b5467a63dffa2dc9d9e069caf075d16fc33fdd4c3b01bfadae6433767d93``

///
/// expected public key:
/// `b7a3c12dc0c8c748ab07525b701122b88bd78f600c76342d27f25e5f92444cde`
///
Expand Down Expand Up @@ -180,10 +183,12 @@ mod tests {
pk.to_hex(),
"4cb5abf6ad79fbf5abbccafcc269d85cd2651ed4b885b5869f241aedf0a5ba29"
);
let sig = ScryptoEd25519Signature::from_str("cf0ca64435609b85ab170da339d415bbac87d678dfd505969be20adc6b5971f4ee4b4620c602bcbc34fd347596546675099d696265f4a42a16df343da1af980e").unwrap();
let sig_hex = "cf0ca64435609b85ab170da339d415bbac87d678dfd505969be20adc6b5971f4ee4b4620c602bcbc34fd347596546675099d696265f4a42a16df343da1af980e";
let sig = Ed25519Signature::from_str(sig_hex).unwrap();

assert_eq!(sk.sign(&msg), sig);
assert!(pk.is_valid(&sig, &msg))
assert!(pk.is_valid(&sig, &msg));
assert_eq!(sig.to_hex(), sig_hex);
}

#[test]
Expand Down
10 changes: 7 additions & 3 deletions src/core/types/keys/ed25519/public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,18 @@ pub fn ed25519_public_key_to_bytes(public_key: &Ed25519PublicKey) -> Vec<u8> {
public_key.to_bytes()
}

impl IsPublicKey<ScryptoEd25519Signature> for Ed25519PublicKey {
impl IsPublicKey<Ed25519Signature> for Ed25519PublicKey {
/// Verifies an EdDSA signature over Curve25519.
fn is_valid(
&self,
signature: &ScryptoEd25519Signature,
signature: &Ed25519Signature,
for_hash: &impl IsHash,
) -> bool {
scrypto_verify_ed25519(for_hash.as_hash(), &self.to_engine(), signature)
scrypto_verify_ed25519(
for_hash.as_hash(),
&self.to_engine(),
&signature.clone().into(),
)
}
}

Expand Down
11 changes: 6 additions & 5 deletions src/core/types/keys/secp256k1/private_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::prelude::*;

use radix_engine_common::crypto::{
IsHash, Secp256k1PrivateKey as ScryptoSecp256k1PrivateKey,
Secp256k1Signature as ScryptoSecp256k1Signature,
};

/// A secp256k1 private key used to create cryptographic signatures, more specifically
Expand Down Expand Up @@ -85,7 +84,7 @@ impl IsPrivateKey<Secp256k1PublicKey> for Secp256k1PrivateKey {
SLIP10Curve::Secp256k1
}

type Signature = ScryptoSecp256k1Signature;
type Signature = Secp256k1Signature;

fn public_key(&self) -> Secp256k1PublicKey {
Secp256k1PublicKey::try_from(self.0.public_key()).expect(
Expand All @@ -94,7 +93,7 @@ impl IsPrivateKey<Secp256k1PublicKey> for Secp256k1PrivateKey {
}

fn sign(&self, msg_hash: &impl IsHash) -> Self::Signature {
self.0.sign(msg_hash)
self.0.sign(msg_hash).into()
}
}

Expand Down Expand Up @@ -182,10 +181,12 @@ mod tests {
pk.to_hex(),
"0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
);
let sig = ScryptoSecp256k1Signature::from_str("00eb8dcd5bb841430dd0a6f45565a1b8bdb4a204eb868832cd006f963a89a662813ab844a542fcdbfda4086a83fbbde516214113051b9c8e42a206c98d564d7122").unwrap();
let sig_hex = "00eb8dcd5bb841430dd0a6f45565a1b8bdb4a204eb868832cd006f963a89a662813ab844a542fcdbfda4086a83fbbde516214113051b9c8e42a206c98d564d7122";
let sig = Secp256k1Signature::from_str(sig_hex).unwrap();

assert_eq!(sk.sign(&msg), sig);
assert!(pk.is_valid(&sig, &msg))
assert!(pk.is_valid(&sig, &msg));
assert_eq!(sig.to_hex(), sig_hex);
}

#[test]
Expand Down
14 changes: 8 additions & 6 deletions src/core/types/keys/secp256k1/public_key.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
use crate::{prelude::*, UniffiCustomTypeConverter};

use bip32::secp256k1::PublicKey as BIP32Secp256k1PublicKey; // the bip32 crate actually does validation of the PublicKey whereas `radix_engine_common` does not.

use radix_engine_common::crypto::{
verify_secp256k1, Hash, IsHash,
Secp256k1PublicKey as ScryptoSecp256k1PublicKey,
Secp256k1Signature as ScryptoSecp256k1Signature,
};
// use transaction::{
// signing::secp256k1::Secp256k1Signature, validation::verify_secp256k1,
// };

/// A `secp256k1` public key used to verify cryptographic signatures (ECDSA signatures).
#[serde_as]
Expand Down Expand Up @@ -85,14 +83,18 @@ pub fn new_secp256k1_public_key_placeholder_other() -> Secp256k1PublicKey {
Secp256k1PublicKey::placeholder_other()
}

impl IsPublicKey<ScryptoSecp256k1Signature> for Secp256k1PublicKey {
impl IsPublicKey<Secp256k1Signature> for Secp256k1PublicKey {
/// Verifies an ECDSA signature over Secp256k1.
fn is_valid(
&self,
signature: &ScryptoSecp256k1Signature,
signature: &Secp256k1Signature,
for_hash: &impl IsHash,
) -> bool {
verify_secp256k1(for_hash.as_hash(), &self.to_engine(), signature)
verify_secp256k1(
for_hash.as_hash(),
&self.to_engine(),
&signature.clone().into(),
)
}
}

Expand Down
65 changes: 44 additions & 21 deletions src/core/types/signatures/ed25519_signature.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,46 @@
// use crate::prelude::*;
use crate::prelude::*;

// use radix_engine_common::crypto::Ed25519Signature as ScryptoEd25519Signature;
use radix_engine_common::crypto::Ed25519Signature as ScryptoEd25519Signature;

// /// Represents an ED25519 signature.
// #[derive(
// Clone,
// PartialEq,
// Eq,
// PartialOrd,
// Ord,
// Hash,
// SerializeDisplay,
// DeserializeFromStr,
// derive_more::Display,
// derive_more::Debug,
// uniffi::Record,
// )]
// #[display("{}", self.to_hex())]
// #[debug("{}", self.to_hex())]
// pub struct Ed25519Signature {
// pub bytes: BagOfBytes,
// }
/// Represents an ED25519 signature.
#[derive(
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
derive_more::Display,
derive_more::Debug,
derive_more::FromStr,
uniffi::Record,
)]
#[display("{}", self.to_hex())]
#[debug("{}", self.to_hex())]
pub struct Ed25519Signature {
pub bytes: Hex64Bytes,
}

impl From<ScryptoEd25519Signature> for Ed25519Signature {
fn from(value: ScryptoEd25519Signature) -> Self {
Self {
bytes: Hex64Bytes::from_bytes(&value.0),
}
}
}

impl From<Ed25519Signature> for ScryptoEd25519Signature {
fn from(value: Ed25519Signature) -> Self {
ScryptoEd25519Signature(value.bytes.bytes())
}
}

impl Ed25519Signature {
pub fn to_bytes(&self) -> Vec<u8> {
self.bytes.to_vec()
}

pub fn to_hex(&self) -> String {
hex_encode(self.to_bytes())
}
}
48 changes: 46 additions & 2 deletions src/core/types/signatures/secp256k1_signature.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,47 @@
// use crate::prelude::*;
use crate::prelude::*;

// use radix_engine_common::crypto::Secp256k1Signature as ScryptoSecp256k1Signature;
use radix_engine_common::crypto::Secp256k1Signature as ScryptoSecp256k1Signature;

/// Represents an Secp256k1 signature.
#[derive(
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
derive_more::Display,
derive_more::Debug,
derive_more::FromStr,
uniffi::Record,
)]
#[display("{}", self.to_hex())]
#[debug("{}", self.to_hex())]
pub struct Secp256k1Signature {
// recovery id + signature
pub bytes: Hex65Bytes,
}

impl From<ScryptoSecp256k1Signature> for Secp256k1Signature {
fn from(value: ScryptoSecp256k1Signature) -> Self {
Self {
bytes: Hex65Bytes::from_bytes(&value.0),
}
}
}

impl From<Secp256k1Signature> for ScryptoSecp256k1Signature {
fn from(value: Secp256k1Signature) -> Self {
ScryptoSecp256k1Signature(value.bytes.bytes())
}
}

impl Secp256k1Signature {
pub fn to_bytes(&self) -> Vec<u8> {
self.bytes.to_vec()
}

pub fn to_hex(&self) -> String {
hex_encode(self.to_bytes())
}
}
47 changes: 27 additions & 20 deletions src/core/types/signatures/signature.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
// use crate::prelude::*;
use crate::prelude::*;

// #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
// pub enum SignatureV1 {
// Secp256k1(Secp256k1Signature),
// Ed25519(Ed25519Signature),
// }
#[derive(
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
EnumAsInner,
derive_more::Display,
derive_more::Debug,
uniffi::Enum,
)]
pub enum Signature {
Secp256k1 { value: Secp256k1Signature },
Ed25519 { value: Ed25519Signature },
}

// impl From<Secp256k1Signature> for SignatureV1 {
// fn from(signature: Secp256k1Signature) -> Self {
// Self::Secp256k1(signature)
// }
// }
impl From<Secp256k1Signature> for Signature {
fn from(signature: Secp256k1Signature) -> Self {

Check warning on line 21 in src/core/types/signatures/signature.rs

View check run for this annotation

Codecov / codecov/patch

src/core/types/signatures/signature.rs#L21

Added line #L21 was not covered by tests
Self::Secp256k1 { value: signature }
}
}

// impl From<Ed25519Signature> for SignatureV1 {
// fn from(signature: Ed25519Signature) -> Self {
// Self::Ed25519(signature)
// }
// }

// #[derive(Debug, Clone, Eq, PartialEq, ManifestSbor)]
// #[sbor(transparent)]
// pub struct NotarySignatureV1(pub SignatureV1);
impl From<Ed25519Signature> for Signature {
fn from(signature: Ed25519Signature) -> Self {

Check warning on line 27 in src/core/types/signatures/signature.rs

View check run for this annotation

Codecov / codecov/patch

src/core/types/signatures/signature.rs#L27

Added line #L27 was not covered by tests
Self::Ed25519 { value: signature }
}
}

0 comments on commit 5f5cc20

Please sign in to comment.