Skip to content

Commit

Permalink
wip on extending SSI length
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Sep 12, 2024
1 parent d921b97 commit af465b9
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 68 deletions.
34 changes: 13 additions & 21 deletions src/bip340.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ use secp256k1::{Keypair, Message, SecretKey, XOnlyPublicKey, SECP256K1};
use crate::{Algo, Chain, InvalidPubkey, InvalidSig, SsiPub, SsiSig};

#[derive(Clone, Eq, PartialEq, From)]
pub struct Bip340Secret(pub(crate) SecretKey);
pub struct Bip340Secret {
chain: Chain,
algo: Algo,
key: SecretKey,
}

impl Ord for Bip340Secret {
fn cmp(&self, other: &Self) -> Ordering { self.0.secret_bytes().cmp(&other.0.secret_bytes()) }
Expand All @@ -42,33 +46,21 @@ impl Hash for Bip340Secret {
fn hash<H: Hasher>(&self, state: &mut H) { self.0.secret_bytes().hash(state) }
}

impl From<Bip340Secret> for [u8; 32] {
fn from(ssi: Bip340Secret) -> Self { ssi.0.secret_bytes() }
}

impl From<[u8; 32]> for Bip340Secret {
fn from(value: [u8; 32]) -> Self {
Self(SecretKey::from_slice(&value).expect("invalid secret key"))
}
}

impl Bip340Secret {
pub fn new(chain: Chain) -> Self {
use rand::thread_rng;
loop {
let sk = SecretKey::new(&mut thread_rng());
let (pk, _) = sk.x_only_public_key(SECP256K1);
let data = pk.serialize();
if data[30] == u8::from(Algo::Bip340) && data[31] == u8::from(chain) {
return Self(sk);
}
let key = SecretKey::new(&mut thread_rng());
Self {
chain,
algo: Algo::Bip340,
key,
}
}

pub fn to_public(&self) -> SsiPub {
let (pk, _) = self.0.x_only_public_key(SECP256K1);
pub fn to_public(&self, chain: Chain, algo: Algo) -> SsiPub {
let (pk, _) = self.key.x_only_public_key(SECP256K1);
let data = pk.serialize();
SsiPub::from(data)
SsiPub::with(chain, algo, data)
}

pub fn sign(&self, msg: [u8; 32]) -> SsiSig {
Expand Down
44 changes: 16 additions & 28 deletions src/ed25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,59 +23,47 @@ use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use std::ops::Deref;

use ec25519::{KeyPair, Noise, PublicKey, SecretKey, Seed, Signature};
use ec25519::{KeyPair, PublicKey, SecretKey, Seed, Signature};

use crate::{Algo, Chain, InvalidPubkey, InvalidSig, SsiPub, SsiSig};

#[derive(Clone, Eq, PartialEq, From)]
pub struct Ed25519Secret(pub(crate) SecretKey);
pub struct Ed25519Secret {
chain: Chain,
algo: Algo,
key: SecretKey,
}

impl Ord for Ed25519Secret {
fn cmp(&self, other: &Self) -> Ordering { self.0.as_slice().cmp(other.0.as_slice()) }
fn cmp(&self, other: &Self) -> Ordering { self.serialize().cmp(other.serialize()) }
}

impl PartialOrd for Ed25519Secret {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
}

impl Hash for Ed25519Secret {
fn hash<H: Hasher>(&self, state: &mut H) { self.0.as_slice().hash(state) }
}

impl From<Ed25519Secret> for [u8; 64] {
fn from(ssi: Ed25519Secret) -> Self { *ssi.0.deref() }
}

impl From<[u8; 64]> for Ed25519Secret {
fn from(value: [u8; 64]) -> Self {
Self(SecretKey::from_slice(&value).expect("invalid secret key"))
}
fn hash<H: Hasher>(&self, state: &mut H) { self.serialize().hash(state) }
}

impl Ed25519Secret {
pub fn new(chain: Chain) -> Self {
loop {
let pair = KeyPair::from_seed(Seed::generate());
let pk = pair.pk;

if pk[30] != u8::from(Algo::Ed25519) || pk[31] != u8::from(chain) {
continue;
}

let sig = pair.sk.sign("test", Some(Noise::generate()));
pk.verify("test", &sig).expect("unable to create key");
let pair = KeyPair::from_seed(Seed::generate());

return Self(pair.sk);
Self {
chain,
algo: Algo::Ed25519,
key: pair.sk,
}
}

pub fn to_public(&self) -> SsiPub {
let pk = self.0.public_key();
SsiPub::from(*pk)
let pk = self.key.public_key();
SsiPub::with(self.chain, self.algo, *pk)
}

pub fn sign(&self, msg: [u8; 32]) -> SsiSig {
let sig = self.0.sign(msg, None);
let sig = self.key.sign(msg, None);
SsiSig::from(*sig)
}
}
Expand Down
46 changes: 30 additions & 16 deletions src/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,35 +187,49 @@ impl Chain {
pub struct SsiPub {
chain: Chain,
algo: Algo,
key: Bytes<30>,
key: Bytes32,
}

impl DisplayBaid64 for SsiPub {
impl DisplayBaid64<34> for SsiPub {
const HRI: &'static str = "ssi";
const CHUNKING: bool = true;
const PREFIX: bool = true;
const EMBED_CHECKSUM: bool = false;
const MNEMONIC: bool = false;

fn to_baid64_payload(&self) -> [u8; 32] { <[u8; 32]>::from(*self) }
fn to_baid64_payload(&self) -> [u8; 34] { <[u8; 34]>::from(*self) }
}

impl FromBaid64Str for SsiPub {}
impl FromBaid64Str<34> for SsiPub {}

impl From<SsiPub> for [u8; 32] {
fn from(ssi: SsiPub) -> Self { ssi.to_byte_array() }
impl From<SsiPub> for [u8; 34] {
fn from(ssi: SsiPub) -> Self {
let mut bytes = [0u8; 34];
bytes[0] = ssi.algo.to_u8();
bytes[1] = ssi.chain.to_u8();
bytes[2..].copy_from_slice(&ssi.to_byte_array());
bytes
}
}

impl From<[u8; 32]> for SsiPub {
fn from(value: [u8; 32]) -> Self {
let key = Bytes::from_slice_unsafe(&value[0..30]);
let algo = Algo::from(value[30]);
let chain = Chain::from(value[31]);
impl From<[u8; 34]> for SsiPub {
fn from(value: [u8; 34]) -> Self {
let algo = Algo::from(value[0]);
let chain = Chain::from(value[1]);
let key = Bytes::from_slice_unsafe(&value[2..]);
Self { algo, key, chain }
}
}

impl SsiPub {
pub fn with(chain: Chain, algo: Algo, key: impl Into<[u8; 32]>) -> Self {
Self {
chain,
algo,
key: Bytes32::from(key.into()),
}
}

pub fn verify_text(self, text: &str, sig: SsiSig) -> Result<(), InvalidSig> {
let msg = Sha256::digest(text);
let digest = Sha256::digest(msg);
Expand All @@ -234,11 +248,11 @@ impl SsiPub {
Fingerprint([self.key[0], self.key[1], self.key[2], self.key[3], self.key[4], self.key[5]])
}

pub fn to_byte_array(&self) -> [u8; 32] {
let mut buf = [0u8; 32];
buf[0..30].copy_from_slice(self.key.as_slice());
buf[30] = self.algo.into();
buf[31] = self.chain.into();
pub fn to_byte_array(&self) -> [u8; 34] {
let mut buf = [0u8; 34];
buf[0] = self.algo.into();
buf[1] = self.chain.into();
buf[2..32].copy_from_slice(self.key.as_slice());
buf
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,17 @@ pub struct EncryptedSecret {
pub fp: Fingerprint,
pub nonce: Nonce<Aes256Gcm>,
pub algo: Algo,
pub chain: Chain,
pub key: Vec<u8>,
}

impl EncryptedSecret {
pub fn reveal(&self, passwd: impl AsRef<str>) -> Result<SsiSecret, RevealError> {
let sk = decrypt(&self.key, self.nonce, passwd.as_ref())?;
match self.algo {
Algo::Ed25519 => Ok(ec25519::SecretKey::from_slice(&sk)?.into()),
Algo::Ed25519 => {
Ok(Ed25519Secret::with(self.chain, ec25519::SecretKey::from_slice(&sk)?).into())
}
Algo::Bip340 => Ok(secp256k1::SecretKey::from_slice(&sk)?.into()),
Algo::Other(algo) => Err(RevealError::Unsupported(algo)),
}
Expand Down Expand Up @@ -148,10 +151,8 @@ impl Display for EncryptedSecret {
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, From)]
pub enum SsiSecret {
#[from]
#[from(secp256k1::SecretKey)]
Bip340(Bip340Secret),
#[from]
#[from(ec25519::SecretKey)]
Ed25519(Ed25519Secret),
}

Expand Down

0 comments on commit af465b9

Please sign in to comment.