Skip to content
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
5d3dce1
First definition for pair public keys
drskalman Aug 3, 2023
be890d4
Two example of implementation of pair for demonestration
drskalman Aug 3, 2023
fb6a018
- implement paired crypto `Public` as tuple of two `Public`s - unsuce…
drskalman Aug 14, 2023
62ef8b1
keep both public key object and their continous serialization in pair…
drskalman Aug 21, 2023
8d4e523
implement PassBy and From<Pair> for paired_crypto
drskalman Aug 21, 2023
eea74e2
implement rest of aux traits for `paired_crypto::Public` implement so…
drskalman Aug 22, 2023
f407d87
Attempt to implement trait `Pair` for `pair_cyrpto::Pair`
drskalman Aug 29, 2023
2606cc4
- Implement trait `Pair` for `paired_crypto::Pair` - Implement a pair…
drskalman Aug 31, 2023
00933da
implement sgin and verify for
drskalman Sep 5, 2023
e7719ab
Actually implementing `paired_crypto::{Pair, Public, Signatrue}` for …
drskalman Sep 10, 2023
7a9b677
Implement and pass all test for `paired_crypto`
drskalman Sep 11, 2023
a01a814
- move to signle seed for both schemes in `primitives/core/src/paired…
drskalman Sep 25, 2023
7c02658
replace `hex!` → `array_bytes::hex2xx`
drskalman Sep 25, 2023
7f8d958
Apply suggestions from `paired_crypto` code review on type nam, hash …
drskalman Oct 5, 2023
eef2cec
Do not panic in `paired::Signature::try_from`
drskalman Oct 5, 2023
efb215f
Remove `DoublePair` trait.
drskalman Oct 5, 2023
65584bd
Do not empty implement `paired::Pair`
drskalman Oct 5, 2023
e047f75
Use `paired_crypto::Seed` instead of `[u8; SECURE_SEED_LEN]`
drskalman Oct 5, 2023
c12b82e
use `ecdsa::PUBLIC_KEY_SERIALIZED_SIZE` and `ecdsa::SIGNATURE_SERIALI…
drskalman Oct 5, 2023
dba854a
Remove `paired::DoublePair` impl as well
drskalman Oct 5, 2023
5182c86
- Implement `BytesArray` for both ecdsa and bls Signatures
drskalman Oct 5, 2023
17d0077
Implement encode_and_decode_(public_key/signature)_works test for pai…
drskalman Oct 5, 2023
a740589
cargo fmt
drskalman Oct 5, 2023
7e34167
Merge branch 'master' into skalman-paired-crypto-scheme
drskalman Oct 5, 2023
6c0c107
Cleanup
davxy Oct 7, 2023
67152d8
Remove TODO
davxy Oct 7, 2023
a0cc64e
Merge pull request #1 from davxy/skalman-paired-crypto-scheme
drskalman Oct 7, 2023
685c21d
Put (De)serialization under `serde` feature instead of `std` in bls a…
drskalman Oct 7, 2023
9b46ba8
cargo +nightly fmt
drskalman Oct 7, 2023
9fbd4d2
Make clippy happy
davxy Oct 7, 2023
b28d0ad
Fix
davxy Oct 7, 2023
78c75e3
More tweaks
davxy Oct 7, 2023
96acd6c
Ss58 requires serde
davxy Oct 7, 2023
3c4311a
Tweaks
davxy Oct 8, 2023
6aa8281
Fix typo
davxy Oct 8, 2023
f568441
- replace `unwrap` with `expect`
drskalman Oct 10, 2023
1e3b915
Merge branch 'skalman-paired-crypto-scheme' of https://github.com/w3f…
drskalman Oct 10, 2023
f07f05a
Rename `TraitPair` -> `PairT`
drskalman Oct 10, 2023
a6da3f5
Remove internal Left and Right Public and Signature objects.
drskalman Oct 10, 2023
a069dcd
Trivial things
davxy Oct 11, 2023
808a53d
Update substrate/primitives/core/src/paired_crypto.rs
drskalman Oct 11, 2023
616f503
Merge branch 'master' into skalman-paired-crypto-scheme
drskalman Oct 11, 2023
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
44 changes: 26 additions & 18 deletions substrate/primitives/core/src/bls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

//! Simple BLS (Boneh–Lynn–Shacham) Signature API.

#[cfg(feature = "std")]
#[cfg(feature = "serde")]
use crate::crypto::Ss58Codec;
use crate::crypto::{ByteArray, CryptoType, Derive, Public as TraitPublic, UncheckedFrom};
#[cfg(feature = "full_crypto")]
Expand All @@ -28,8 +28,12 @@ use sp_std::vec::Vec;

use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
#[cfg(feature = "std")]

#[cfg(feature = "serde")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
#[cfg(all(not(feature = "std"), feature = "serde"))]
use sp_std::alloc::{format, string::String};

use w3f_bls::{DoublePublicKey, DoubleSignature, EngineBLS, SerializableToBytes, TinyBLS381};
#[cfg(feature = "full_crypto")]
use w3f_bls::{DoublePublicKeyScheme, Keypair, Message, SecretKey};
Expand All @@ -39,6 +43,7 @@ use sp_std::{convert::TryFrom, marker::PhantomData, ops::Deref};

/// BLS-377 specialized types
pub mod bls377 {
pub use super::{PUBLIC_KEY_SERIALIZED_SIZE, SIGNATURE_SERIALIZED_SIZE};
use crate::crypto::CryptoTypeId;
use w3f_bls::TinyBLS377;

Expand All @@ -60,6 +65,7 @@ pub mod bls377 {

/// BLS-381 specialized types
pub mod bls381 {
pub use super::{PUBLIC_KEY_SERIALIZED_SIZE, SIGNATURE_SERIALIZED_SIZE};
use crate::crypto::CryptoTypeId;
use w3f_bls::TinyBLS381;

Expand All @@ -83,17 +89,17 @@ trait BlsBound: EngineBLS + HardJunctionId + Send + Sync + 'static {}

impl<T: EngineBLS + HardJunctionId + Send + Sync + 'static> BlsBound for T {}

// Secret key serialized size
/// Secret key serialized size
#[cfg(feature = "full_crypto")]
const SECRET_KEY_SERIALIZED_SIZE: usize =
<SecretKey<TinyBLS381> as SerializableToBytes>::SERIALIZED_BYTES_SIZE;

// Public key serialized size
const PUBLIC_KEY_SERIALIZED_SIZE: usize =
/// Public key serialized size
pub const PUBLIC_KEY_SERIALIZED_SIZE: usize =
<DoublePublicKey<TinyBLS381> as SerializableToBytes>::SERIALIZED_BYTES_SIZE;

// Signature serialized size
const SIGNATURE_SERIALIZED_SIZE: usize =
/// Signature serialized size
pub const SIGNATURE_SERIALIZED_SIZE: usize =
<DoubleSignature<TinyBLS381> as SerializableToBytes>::SERIALIZED_BYTES_SIZE;

/// A secret seed.
Expand Down Expand Up @@ -258,7 +264,7 @@ impl<T> sp_std::fmt::Debug for Public<T> {
}
}

#[cfg(feature = "std")]
#[cfg(feature = "serde")]
impl<T: BlsBound> Serialize for Public<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand All @@ -268,7 +274,7 @@ impl<T: BlsBound> Serialize for Public<T> {
}
}

#[cfg(feature = "std")]
#[cfg(feature = "serde")]
impl<'de, T: BlsBound> Deserialize<'de> for Public<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand Down Expand Up @@ -317,6 +323,10 @@ impl<T> sp_std::hash::Hash for Signature<T> {
}
}

impl<T> ByteArray for Signature<T> {
const LEN: usize = SIGNATURE_SERIALIZED_SIZE;
}

impl<T> TryFrom<&[u8]> for Signature<T> {
type Error = ();

Expand All @@ -330,7 +340,7 @@ impl<T> TryFrom<&[u8]> for Signature<T> {
}
}

#[cfg(feature = "std")]
#[cfg(feature = "serde")]
impl<T> Serialize for Signature<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand All @@ -340,7 +350,7 @@ impl<T> Serialize for Signature<T> {
}
}

#[cfg(feature = "std")]
#[cfg(feature = "serde")]
impl<'de, T> Deserialize<'de> for Signature<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand Down Expand Up @@ -444,10 +454,9 @@ impl<T: BlsBound> TraitPair for Pair<T> {
path: Iter,
_seed: Option<Seed>,
) -> Result<(Self, Option<Seed>), DeriveError> {
let mut acc: [u8; SECRET_KEY_SERIALIZED_SIZE] =
self.0.secret.to_bytes().try_into().expect(
"Secret key serializer returns a vector of SECRET_KEY_SERIALIZED_SIZE size",
);
let mut acc: [u8; SECRET_KEY_SERIALIZED_SIZE] = self.0.secret.to_bytes().try_into().expect(
"Secret key serializer returns a vector of SECRET_KEY_SERIALIZED_SIZE size; qed",
);
for j in path {
match j {
DeriveJunction::Soft(_cc) => return Err(DeriveError::SoftKeyInPath),
Expand Down Expand Up @@ -529,11 +538,10 @@ mod test {
);
}

// Only passes if the seed = (seed mod ScalarField)
#[test]
fn seed_and_derive_should_work() {
let seed = array_bytes::hex2array_unchecked(
"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f00",
"9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60",
);
let pair = Pair::from_seed(&seed);
// we are using hash to field so this is not going to work
Expand All @@ -543,7 +551,7 @@ mod test {
assert_eq!(
derived.to_raw_vec(),
array_bytes::hex2array_unchecked::<_, 32>(
"a4f2269333b3e87c577aa00c4a2cd650b3b30b2e8c286a47c251279ff3a26e0d"
"3a0626d095148813cd1642d38254f1cfff7eb8cc1a2fc83b2a135377c3554c12"
)
);
}
Expand Down
2 changes: 1 addition & 1 deletion substrate/primitives/core/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,7 @@ macro_rules! impl_from_entropy_base {
[$type; 17], [$type; 18], [$type; 19], [$type; 20], [$type; 21], [$type; 22], [$type; 23], [$type; 24],
[$type; 25], [$type; 26], [$type; 27], [$type; 28], [$type; 29], [$type; 30], [$type; 31], [$type; 32],
[$type; 36], [$type; 40], [$type; 44], [$type; 48], [$type; 56], [$type; 64], [$type; 72], [$type; 80],
[$type; 96], [$type; 112], [$type; 128], [$type; 160], [$type; 192], [$type; 224], [$type; 256]
[$type; 96], [$type; 112], [$type; 128], [$type; 160], [$type; 177], [$type; 192], [$type; 224], [$type; 256]
);
}
}
Expand Down
54 changes: 32 additions & 22 deletions substrate/primitives/core/src/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ use sp_std::vec::Vec;
/// An identifier used to match public keys against ecdsa keys
pub const CRYPTO_ID: CryptoTypeId = CryptoTypeId(*b"ecds");

/// The byte length of public key
pub const PUBLIC_KEY_SERIALIZED_SIZE: usize = 33;

/// The byte length of signature
pub const SIGNATURE_SERIALIZED_SIZE: usize = 65;

/// A secret seed (which is bytewise essentially equivalent to a SecretKey).
///
/// We need it as a different type because `Seed` is expected to be AsRef<[u8]>.
Expand All @@ -71,11 +77,11 @@ type Seed = [u8; 32];
PartialOrd,
Ord,
)]
pub struct Public(pub [u8; 33]);
pub struct Public(pub [u8; PUBLIC_KEY_SERIALIZED_SIZE]);

impl crate::crypto::FromEntropy for Public {
fn from_entropy(input: &mut impl codec::Input) -> Result<Self, codec::Error> {
let mut result = Self([0u8; 33]);
let mut result = Self([0u8; PUBLIC_KEY_SERIALIZED_SIZE]);
input.read(&mut result.0[..])?;
Ok(result)
}
Expand All @@ -86,7 +92,7 @@ impl Public {
///
/// NOTE: No checking goes on to ensure this is a real public key. Only use it if
/// you are certain that the array actually is a pubkey. GIGO!
pub fn from_raw(data: [u8; 33]) -> Self {
pub fn from_raw(data: [u8; PUBLIC_KEY_SERIALIZED_SIZE]) -> Self {
Self(data)
}

Expand All @@ -109,7 +115,7 @@ impl Public {
}

impl ByteArray for Public {
const LEN: usize = 33;
const LEN: usize = PUBLIC_KEY_SERIALIZED_SIZE;
}

impl TraitPublic for Public {}
Expand Down Expand Up @@ -148,8 +154,8 @@ impl From<Pair> for Public {
}
}

impl UncheckedFrom<[u8; 33]> for Public {
fn unchecked_from(x: [u8; 33]) -> Self {
impl UncheckedFrom<[u8; PUBLIC_KEY_SERIALIZED_SIZE]> for Public {
fn unchecked_from(x: [u8; PUBLIC_KEY_SERIALIZED_SIZE]) -> Self {
Public(x)
}
}
Expand Down Expand Up @@ -198,14 +204,18 @@ impl<'de> Deserialize<'de> for Public {
/// A signature (a 512-bit value, plus 8 bits for recovery ID).
#[cfg_attr(feature = "full_crypto", derive(Hash))]
#[derive(Encode, Decode, MaxEncodedLen, PassByInner, TypeInfo, PartialEq, Eq)]
pub struct Signature(pub [u8; 65]);
pub struct Signature(pub [u8; SIGNATURE_SERIALIZED_SIZE]);

impl ByteArray for Signature {
const LEN: usize = SIGNATURE_SERIALIZED_SIZE;
}

impl TryFrom<&[u8]> for Signature {
type Error = ();

fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
if data.len() == 65 {
let mut inner = [0u8; 65];
if data.len() == SIGNATURE_SERIALIZED_SIZE {
let mut inner = [0u8; SIGNATURE_SERIALIZED_SIZE];
inner.copy_from_slice(data);
Ok(Signature(inner))
} else {
Expand Down Expand Up @@ -239,26 +249,26 @@ impl<'de> Deserialize<'de> for Signature {

impl Clone for Signature {
fn clone(&self) -> Self {
let mut r = [0u8; 65];
let mut r = [0u8; SIGNATURE_SERIALIZED_SIZE];
r.copy_from_slice(&self.0[..]);
Signature(r)
}
}

impl Default for Signature {
fn default() -> Self {
Signature([0u8; 65])
Signature([0u8; SIGNATURE_SERIALIZED_SIZE])
}
}

impl From<Signature> for [u8; 65] {
fn from(v: Signature) -> [u8; 65] {
impl From<Signature> for [u8; SIGNATURE_SERIALIZED_SIZE] {
fn from(v: Signature) -> [u8; SIGNATURE_SERIALIZED_SIZE] {
v.0
}
}

impl AsRef<[u8; 65]> for Signature {
fn as_ref(&self) -> &[u8; 65] {
impl AsRef<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature {
fn as_ref(&self) -> &[u8; SIGNATURE_SERIALIZED_SIZE] {
&self.0
}
}
Expand Down Expand Up @@ -287,8 +297,8 @@ impl sp_std::fmt::Debug for Signature {
}
}

impl UncheckedFrom<[u8; 65]> for Signature {
fn unchecked_from(data: [u8; 65]) -> Signature {
impl UncheckedFrom<[u8; SIGNATURE_SERIALIZED_SIZE]> for Signature {
fn unchecked_from(data: [u8; SIGNATURE_SERIALIZED_SIZE]) -> Signature {
Signature(data)
}
}
Expand All @@ -298,7 +308,7 @@ impl Signature {
///
/// NOTE: No checking goes on to ensure this is a real signature. Only use it if
/// you are certain that the array actually is a signature. GIGO!
pub fn from_raw(data: [u8; 65]) -> Signature {
pub fn from_raw(data: [u8; SIGNATURE_SERIALIZED_SIZE]) -> Signature {
Signature(data)
}

Expand All @@ -307,10 +317,10 @@ impl Signature {
/// NOTE: No checking goes on to ensure this is a real signature. Only use it if
/// you are certain that the array actually is a signature. GIGO!
pub fn from_slice(data: &[u8]) -> Option<Self> {
if data.len() != 65 {
if data.len() != SIGNATURE_SERIALIZED_SIZE {
return None
}
let mut r = [0u8; 65];
let mut r = [0u8; SIGNATURE_SERIALIZED_SIZE];
r.copy_from_slice(data);
Some(Signature(r))
}
Expand Down Expand Up @@ -473,7 +483,7 @@ impl Pair {
pub fn verify_deprecated<M: AsRef<[u8]>>(sig: &Signature, message: M, pubkey: &Public) -> bool {
let message = libsecp256k1::Message::parse(&blake2_256(message.as_ref()));

let parse_signature_overflowing = |x: [u8; 65]| {
let parse_signature_overflowing = |x: [u8; SIGNATURE_SERIALIZED_SIZE]| {
let sig = libsecp256k1::Signature::parse_overflowing_slice(&x[..64]).ok()?;
let rid = libsecp256k1::RecoveryId::parse(x[64]).ok()?;
Some((sig, rid))
Expand Down Expand Up @@ -726,7 +736,7 @@ mod test {
let signature = pair.sign(&message[..]);
let serialized_signature = serde_json::to_string(&signature).unwrap();
// Signature is 65 bytes, so 130 chars + 2 quote chars
assert_eq!(serialized_signature.len(), 132);
assert_eq!(serialized_signature.len(), SIGNATURE_SERIALIZED_SIZE * 2 + 2);
let signature = serde_json::from_str(&serialized_signature).unwrap();
assert!(Pair::verify(&signature, &message[..], &pair.public()));
}
Expand Down
2 changes: 1 addition & 1 deletion substrate/primitives/core/src/hexdisplay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ macro_rules! impl_non_endians {
impl_non_endians!(
[u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], [u8; 10], [u8; 12],
[u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], [u8; 48], [u8; 56],
[u8; 64], [u8; 65], [u8; 80], [u8; 96], [u8; 112], [u8; 128], [u8; 144]
[u8; 64], [u8; 65], [u8; 80], [u8; 96], [u8; 112], [u8; 128], [u8; 144], [u8; 177]
);

/// Format into ASCII + # + hex, suitable for storage key preimages.
Expand Down
1 change: 1 addition & 0 deletions substrate/primitives/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub mod hash;
#[cfg(feature = "std")]
mod hasher;
pub mod offchain;
pub mod paired_crypto;
pub mod sr25519;
pub mod testing;
#[cfg(feature = "std")]
Expand Down
Loading