Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 3 additions & 5 deletions crates/iota-sdk-crypto/src/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,13 @@ impl Ed25519PrivateKey {
}
}

impl crate::ToBytes for Ed25519PrivateKey {
impl crate::ToFromBytes for Ed25519PrivateKey {
type Error = crate::PrivateKeyError;

/// Return the raw 32-byte private key
fn to_bytes(&self) -> Vec<u8> {
self.0.to_bytes().to_vec()
}
}

impl crate::FromBytes for Ed25519PrivateKey {
type Error = crate::PrivateKeyError;

fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() != Self::LENGTH {
Expand Down
121 changes: 105 additions & 16 deletions crates/iota-sdk-crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,32 +197,29 @@ pub const DERIVATION_PATH_PURPOSE_SECP256K1: u32 = 54;
#[cfg(feature = "mnemonic")]
pub const DERIVATION_PATH_PURPOSE_SECP256R1: u32 = 74;

/// Defines a type which can be converted to bytes
pub trait ToBytes {
/// Returns the raw bytes of this type.
fn to_bytes(&self) -> Vec<u8>;
/// Defines the scheme of a private key
pub trait PrivateKeyScheme {
const SCHEME: iota_types::SignatureScheme;

/// Returns the signature scheme for this private key
fn scheme(&self) -> iota_types::SignatureScheme {
Self::SCHEME
}
}

/// Defines a type which can be constructed from bytes
pub trait FromBytes {
pub trait ToFromBytes {
type Error;

/// Returns the raw bytes of this type.
fn to_bytes(&self) -> Vec<u8>;

/// Create an instance from raw bytes
fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Error>
where
Self: Sized;
}

/// Defines the scheme of a private key
pub trait PrivateKeyScheme {
const SCHEME: iota_types::SignatureScheme;

/// Returns the signature scheme for this private key
fn scheme(&self) -> iota_types::SignatureScheme {
Self::SCHEME
}
}

/// Defines a type that can be converted to and from flagged bytes, i.e. bytes
/// prepended by some variant indicator flag
pub trait ToFromFlaggedBytes {
Expand All @@ -237,7 +234,7 @@ pub trait ToFromFlaggedBytes {
Self: Sized;
}

impl<T: ToBytes + FromBytes<Error = PrivateKeyError> + PrivateKeyScheme> ToFromFlaggedBytes for T {
impl<T: ToFromBytes<Error = PrivateKeyError> + PrivateKeyScheme> ToFromFlaggedBytes for T {
type Error = PrivateKeyError;

/// Returns the bytes with signature scheme flag prepended
Expand Down Expand Up @@ -341,3 +338,95 @@ pub trait FromMnemonic {
where
Self: Sized;
}

#[cfg(test)]
mod tests {
use super::*;
use crate::{
ed25519::Ed25519PrivateKey, secp256k1::Secp256k1PrivateKey, secp256r1::Secp256r1PrivateKey,
};

#[cfg(feature = "mnemonic")]
#[test]
fn test_mnemonics_ed25519() {
const TEST_CASES: [[&str; 3]; 3] = [
[
"film crazy soon outside stand loop subway crumble thrive popular green nuclear struggle pistol arm wife phrase warfare march wheat nephew ask sunny firm",
"iotaprivkey1qrqqxhsu3ndp96644fjk4z5ams5ulgmvprklngt2jhvg2ujn5w4q2d2vplv",
"0x9f8e5379678525edf768d7b507dc1ba9016fc4f0eac976ab7f74077d95fba312",
],
[
"require decline left thought grid priority false tiny gasp angle royal system attack beef setup reward aunt skill wasp tray vital bounce inflict level",
"iotaprivkey1qqcxaf57fnenvflpacacaumf6vl0rt0edddhytanvzhkqhwnjk0zspg902d",
"0x862738192e40540e0a5c9a5aca636f53b0cd76b0a9bef3386e05647feb4914ac",
],
[
"organ crash swim stick traffic remember army arctic mesh slice swear summer police vast chaos cradle squirrel hood useless evidence pet hub soap lake",
"iotaprivkey1qzq39vxzm0gq7l8dc5dj5allpuww4mavhwhg8mua4cl3lj2c3fvhcv5l2vn",
"0x2391788ca49c7f0f00699bc2bad45f80c343b4d1df024285c132259433d7ff31",
],
];

for [mnemonic, bech32, address] in TEST_CASES {
let key = Ed25519PrivateKey::from_mnemonic(mnemonic, None, None).unwrap();
assert_eq!(key.to_bech32().unwrap(), bech32);
assert_eq!(key.public_key().derive_address().to_string(), address);
}
}

#[cfg(feature = "mnemonic")]
#[test]
fn test_mnemonics_secp256k1() {
const TEST_CASES: [[&str; 3]; 3] = [
[
"film crazy soon outside stand loop subway crumble thrive popular green nuclear struggle pistol arm wife phrase warfare march wheat nephew ask sunny firm",
"iotaprivkey1q8cy2ll8a0dmzzzwn9zavrug0qf47cyuj6k2r4r6rnjtpjhrdh52vpegd4f",
"0x8520d58dde1ab268349b9a46e5124ae6fe7e4c61df4ca2bc9c97d3c4d07b0b55",
],
[
"require decline left thought grid priority false tiny gasp angle royal system attack beef setup reward aunt skill wasp tray vital bounce inflict level",
"iotaprivkey1q9hm330d05jcxfvmztv046p8kclyaj39hk6elqghgpq4sz4x23hk2wd6cfz",
"0x3740d570eefba29dfc0fdd5829848902064e31ecd059ca05c401907fa8646f61",
],
[
"organ crash swim stick traffic remember army arctic mesh slice swear summer police vast chaos cradle squirrel hood useless evidence pet hub soap lake",
"iotaprivkey1qx2dnch6363h7gdqqfkzmmlequzj4ul3x4fq6dzyajk7wc2c0jgcx32axh5",
"0x943b852c37fef403047e06ff5a2fa216557a4386212fb29554babdd3e1899da5",
],
];

for [mnemonic, bech32, address] in TEST_CASES {
let key = Secp256k1PrivateKey::from_mnemonic(mnemonic, None, None).unwrap();
assert_eq!(key.to_bech32().unwrap(), bech32);
assert_eq!(key.public_key().derive_address().to_string(), address);
}
}

#[cfg(feature = "mnemonic")]
#[test]
fn test_mnemonics_secp256r1() {
const TEST_CASES: [[&str; 3]; 3] = [
[
"act wing dilemma glory episode region allow mad tourist humble muffin oblige",
"iotaprivkey1qtt65ua2lhal76zg4cxd6umdqynv2rj2gzrntp5rwlnyj370jg3pwtqlwdn",
"0x779a63b28528210a5ec6c4af5a70382fa3f0c2d3f98dcbe4e3a4ae2f8c39cc9c",
],
[
"flag rebel cabbage captain minimum purpose long already valley horn enrich salt",
"iotaprivkey1qtcjgmue7q8u4gtutfvfpx3zj3aa2r9pqssuusrltxfv68eqhzsgjc3p4z7",
"0x8b45523042933aa55f57e2ccc661304baed292529b6e67a0c9857c1f3f871806",
],
[
"area renew bar language pudding trial small host remind supreme cabbage era",
"iotaprivkey1qtxafg26qxeqy7f56gd2rvsup0a5kl4cre7nt2rtcrf0p3v5pwd4cgrrff2",
"0x8528ef86150ec331928a8b3edb8adbe2fb523db8c84679aa57a931da6a4cdb25",
],
];

for [mnemonic, bech32, address] in TEST_CASES {
let key = Secp256r1PrivateKey::from_mnemonic(mnemonic, None, None).unwrap();
assert_eq!(key.to_bech32().unwrap(), bech32);
assert_eq!(key.public_key().derive_address().to_string(), address);
}
}
}
12 changes: 5 additions & 7 deletions crates/iota-sdk-crypto/src/secp256k1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,13 @@ impl Secp256k1PrivateKey {
}
}

impl crate::ToBytes for Secp256k1PrivateKey {
impl crate::ToFromBytes for Secp256k1PrivateKey {
type Error = crate::PrivateKeyError;

/// Return the raw 32-byte private key
fn to_bytes(&self) -> Vec<u8> {
self.0.to_bytes().to_vec()
}
}

impl crate::FromBytes for Secp256k1PrivateKey {
type Error = crate::PrivateKeyError;

fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() != Self::LENGTH {
Expand Down Expand Up @@ -154,13 +152,13 @@ impl crate::FromMnemonic for Secp256k1PrivateKey {
) -> Result<Self, Self::Error> {
use std::str::FromStr;

use crate::FromBytes;
use crate::ToFromBytes;

let mnemonic = bip39::Mnemonic::parse_in_normalized(bip39::Language::English, phrase)?;
let seed = mnemonic.to_seed(password.into().unwrap_or_default());
let path = path.into().unwrap_or_else(|| {
format!(
"m/{}'/{}'/0'/0'/0'",
"m/{}'/{}'/0'/0/0",
crate::DERIVATION_PATH_PURPOSE_SECP256K1,
crate::DERIVATION_PATH_COIN_TYPE
)
Expand Down
12 changes: 5 additions & 7 deletions crates/iota-sdk-crypto/src/secp256r1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,13 @@ impl Secp256r1PrivateKey {
}
}

impl crate::ToBytes for Secp256r1PrivateKey {
impl crate::ToFromBytes for Secp256r1PrivateKey {
type Error = crate::PrivateKeyError;

/// Return the raw 32-byte private key
fn to_bytes(&self) -> Vec<u8> {
self.0.to_bytes().to_vec()
}
}

impl crate::FromBytes for Secp256r1PrivateKey {
type Error = crate::PrivateKeyError;

fn from_bytes(bytes: &[u8]) -> Result<Self, Self::Error> {
if bytes.len() != Self::LENGTH {
Expand Down Expand Up @@ -154,14 +152,14 @@ impl crate::FromMnemonic for Secp256r1PrivateKey {
) -> Result<Self, Self::Error> {
use std::str::FromStr;

use crate::FromBytes;
use crate::ToFromBytes;

let mnemonic = bip39::Mnemonic::parse_in_normalized(bip39::Language::English, phrase)?;
let seed = mnemonic.to_seed(password.into().unwrap_or_default());

let path = path.into().unwrap_or_else(|| {
format!(
"m/{}'/{}'/0'/0'/0'",
"m/{}'/{}'/0'/0/0",
crate::DERIVATION_PATH_PURPOSE_SECP256R1,
crate::DERIVATION_PATH_COIN_TYPE
)
Expand Down
2 changes: 1 addition & 1 deletion crates/iota-sdk-crypto/src/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ mod keypair {

/// Encode a SimpleKeypair as `flag || privkey` in bytes
pub fn to_bytes(&self) -> Vec<u8> {
use crate::ToBytes;
use crate::ToFromBytes;

let mut bytes = Vec::new();
bytes.push(self.scheme().to_u8());
Expand Down
2 changes: 1 addition & 1 deletion crates/iota-sdk-ffi/src/crypto/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

use iota_sdk::{
crypto::{FromMnemonic, ToBytes, ToFromBech32},
crypto::{FromMnemonic, ToFromBech32, ToFromBytes},
types::SignatureScheme,
};
use rand::rngs::OsRng;
Expand Down
2 changes: 1 addition & 1 deletion crates/iota-sdk-ffi/src/crypto/secp256k1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

use iota_sdk::{
crypto::{FromMnemonic, ToBytes, ToFromBech32},
crypto::{FromMnemonic, ToFromBech32, ToFromBytes},
types::SignatureScheme,
};
use rand::rngs::OsRng;
Expand Down
2 changes: 1 addition & 1 deletion crates/iota-sdk-ffi/src/crypto/secp256r1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use std::sync::Arc;

use iota_sdk::{
crypto::{FromMnemonic, Signer, ToBytes, ToFromBech32, Verifier},
crypto::{FromMnemonic, Signer, ToFromBech32, ToFromBytes, Verifier},
types::SignatureScheme,
};
use rand::rngs::OsRng;
Expand Down
2 changes: 1 addition & 1 deletion crates/iota-sdk-ffi/src/crypto/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

use iota_sdk::{
crypto::{Signer, ToBytes, ToFromBech32, Verifier},
crypto::{Signer, ToFromBech32, Verifier},
types::SignatureScheme,
};

Expand Down