Skip to content

Commit

Permalink
fix encryption
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Sep 11, 2024
1 parent 2dbf7ed commit d921b97
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 35 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ ascii-armor = "0.7.1"
baid64 = "0.2.2"
base64 = "0.22.1"
secp256k1 = { version = "0.29.0", features = ["rand", "global-context", "rand-std"] }
ec25519 = "0.1.0"
ec25519 = { version = "0.1.0", features = ["blind-keys"] }
rand = "0.8.5"
chrono = "0.4.38"
clap = { version = "4.5.4", features = ["derive"], optional = true }
Expand Down
86 changes: 56 additions & 30 deletions src/encrypt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ use std::str::FromStr;
use aes_gcm::aead::{Aead, Nonce, OsRng};
use aes_gcm::{AeadCore, Aes256Gcm, KeyInit};
use amplify::confinement::{Confined, SmallOrdMap, U64 as U64MAX};
use amplify::{Bytes32, Wrapper};
use amplify::Bytes32;
use armor::{ArmorHeader, ArmorParseError, AsciiArmor};
use ec25519::edwards25519;
use ec25519::{edwards25519, KeyPair, Seed};
use rand::random;
use sha2::{Digest, Sha256};
use strict_encoding::{StrictDeserialize, StrictSerialize};
Expand Down Expand Up @@ -67,8 +67,12 @@ impl AsRef<[u8]> for SymmetricKey {

impl SymmetricKey {
pub fn new() -> Self {
let key = random::<[u8; 32]>();
Self(Bytes32::from_byte_array(key))
loop {
let key = random::<[u8; 32]>();
if edwards25519::GeP3::from_bytes_vartime(&key).is_some() {
return Self(Bytes32::from_byte_array(key));
}
}
}
}

Expand All @@ -77,7 +81,7 @@ impl SymmetricKey {
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_SSI)]
pub struct Encrypted {
pub keys: SmallOrdMap<SsiPub, Bytes32>,
pub keys: SmallOrdMap<SsiPub, (Bytes32, Bytes32)>,
pub nonce: [u8; 12],
pub data: Confined<Vec<u8>, 0, U64MAX>,
}
Expand Down Expand Up @@ -120,11 +124,10 @@ impl Encrypted {
let key = SymmetricKey::new();
let mut keys = bmap![];
for pk in receivers {
keys.insert(
pk,
pk.encrypt_key(&key)
.map_err(|_| EncryptionError::InvalidPubkey(pk))?,
);
let (msg, c1) = pk
.encrypt_key(&key)
.map_err(|_| EncryptionError::InvalidPubkey(pk))?;
keys.insert(pk, (msg, Bytes32::from_slice_unsafe(c1.as_slice())));
}
let (nonce, msg) = encrypt(source, key);
Ok(Self {
Expand All @@ -134,53 +137,76 @@ impl Encrypted {
})
}

pub fn decrypt(&self, pair: SsiPair) -> Result<Vec<u8>, DecryptionError> {
let key = self
pub fn decrypt(&self, pair: impl Into<SsiPair>) -> Result<Vec<u8>, DecryptionError> {
let pair = pair.into();
let (msg, c1) = self
.keys
.iter()
.find(|(pk, _)| *pk == &pair.pk)
.map(|(_, secret)| secret)
.ok_or(DecryptionError::KeyMismatch(pair.pk))?
.copy();
.ok_or(DecryptionError::KeyMismatch(pair.pk))?;
let c1 = ec25519::PublicKey::new(c1.to_byte_array());
let key = pair
.decrypt_key(key)
.decrypt_key(*msg, c1)
.map_err(|_| DecryptionError::InvalidPubkey(pair.pk))?;
Ok(decrypt(self.data.as_slice(), self.nonce.into(), key)?)
}
}

impl SsiPub {
pub fn encrypt_key(&self, key: &SymmetricKey) -> Result<Bytes32, InvalidPubkey> {
pub fn encrypt_key(
&self,
key: &SymmetricKey,
) -> Result<(Bytes32, ec25519::PublicKey), InvalidPubkey> {
match self.algo() {
Algo::Ed25519 => self.encrypt_key_ed25519(key),
Algo::Bip340 | Algo::Other(_) => Err(InvalidPubkey),
}
}

pub fn encrypt_key_ed25519(&self, key: &SymmetricKey) -> Result<Bytes32, InvalidPubkey> {
let ge =
pub fn encrypt_key_ed25519(
&self,
message: &SymmetricKey,
) -> Result<(Bytes32, ec25519::PublicKey), InvalidPubkey> {
let pair = KeyPair::from_seed(Seed::generate());
let y = pair.sk;
let c1 = pair.pk;

let h =
edwards25519::GeP3::from_bytes_vartime(&self.to_byte_array()).ok_or(InvalidPubkey)?;
let s = edwards25519::ge_scalarmult(&y.seed().scalar(), &h);

let m = edwards25519::GeP3::from_bytes_vartime(&message.0.to_byte_array())
.ok_or(InvalidPubkey)?;
let c2 = m + s;

Ok(edwards25519::ge_scalarmult(key.as_ref(), &ge)
.to_bytes()
.into())
Ok((c2.to_bytes().into(), c1))
}
}

impl SsiPair {
pub fn decrypt_key(&self, key: Bytes32) -> Result<SymmetricKey, InvalidPubkey> {
pub fn decrypt_key(
&self,
encrypted_message: Bytes32,
c1: ec25519::PublicKey,
) -> Result<SymmetricKey, InvalidPubkey> {
match self.pk.algo() {
Algo::Ed25519 => self.decrypt_key_ed25519(key),
Algo::Ed25519 => self.decrypt_key_ed25519(encrypted_message, c1),
Algo::Bip340 | Algo::Other(_) => Err(InvalidPubkey),
}
}

pub fn decrypt_key_ed25519(&self, key: Bytes32) -> Result<SymmetricKey, InvalidPubkey> {
let ge = edwards25519::GeP3::from_bytes_negate_vartime(&self.pk.to_byte_array())
pub fn decrypt_key_ed25519(
&self,
encrypted_message: Bytes32,
c1: ec25519::PublicKey,
) -> Result<SymmetricKey, InvalidPubkey> {
let c1 = edwards25519::GeP3::from_bytes_vartime(&c1).ok_or(InvalidPubkey)?;
let s = edwards25519::ge_scalarmult(&self.sk.secret_bytes(), &c1);
let c2 = edwards25519::GeP3::from_bytes_vartime(&encrypted_message.to_byte_array())
.ok_or(InvalidPubkey)?;
Ok(edwards25519::ge_scalarmult(key.as_ref(), &ge)
.to_bytes()
.into())
let key = c2 - s;
Ok(SymmetricKey::from(key.to_bytes()))
}
}

Expand Down Expand Up @@ -228,8 +254,8 @@ mod test {
let sk = SsiSecret::new(Algo::Ed25519, Chain::Bitcoin);
let pair = SsiPair::from(sk);
let key = SymmetricKey::new();
let encrypted = pair.pk.encrypt_key(&key).unwrap();
let decrypted = pair.decrypt_key(encrypted).unwrap();
let (encrypted, c1) = pair.pk.encrypt_key(&key).unwrap();
let decrypted = pair.decrypt_key(encrypted, c1).unwrap();
assert_eq!(key.0, decrypted.0);
}

Expand Down
8 changes: 4 additions & 4 deletions src/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ impl SsiSecret {
}

pub fn conceal(&self, passwd: impl AsRef<str>) -> EncryptedSecret {
let (nonce, key) = encrypt(self.as_secret_bytes().to_vec(), passwd.as_ref());
let (nonce, key) = encrypt(self.secret_bytes().to_vec(), passwd.as_ref());
EncryptedSecret {
fp: self.to_public().fingerprint(),
nonce,
Expand All @@ -224,10 +224,10 @@ impl SsiSecret {
}
}

pub fn as_secret_bytes(&self) -> &[u8] {
pub fn secret_bytes(&self) -> [u8; 32] {
match self {
SsiSecret::Bip340(sk) => sk.0.as_ref(),
SsiSecret::Ed25519(sk) => sk.0.as_ref(),
SsiSecret::Bip340(sk) => sk.0.secret_bytes(),
SsiSecret::Ed25519(sk) => sk.0.seed().scalar(),
}
}
}
Expand Down

0 comments on commit d921b97

Please sign in to comment.