Add tests for asymmetric keys, add public key export
Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
parent
365814b424
commit
7f55cf4fba
@ -101,3 +101,9 @@ impl From<k256::ecdsa::Error> for CryptoError {
|
||||
Self::InvalidKey
|
||||
}
|
||||
}
|
||||
|
||||
impl From<k256::elliptic_curve::Error> for CryptoError {
|
||||
fn from(_: k256::elliptic_curve::Error) -> Self {
|
||||
Self::InvalidKey
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
//! An implementation of asymmetric cryptography using SECP256k1 ECDH with ChaCha20Poly1305
|
||||
//! for the actual encryption.
|
||||
|
||||
use k256::{
|
||||
SecretKey,
|
||||
ecdh::diffie_hellman,
|
||||
};
|
||||
use k256::{SecretKey, ecdh::diffie_hellman, elliptic_curve::sec1::ToEncodedPoint};
|
||||
use sha2::Sha256;
|
||||
|
||||
use crate::{error::CryptoError, key::symmetric::SymmetricKey};
|
||||
@ -18,6 +15,7 @@ pub struct AsymmetricKeypair {
|
||||
}
|
||||
|
||||
/// The public key part of an asymmetric keypair.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct PublicKey(k256::PublicKey);
|
||||
|
||||
impl AsymmetricKeypair {
|
||||
@ -101,12 +99,63 @@ impl AsymmetricKeypair {
|
||||
impl PublicKey {
|
||||
/// Import a public key from raw bytes
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, CryptoError> {
|
||||
if bytes.len() == 64 {
|
||||
Ok(Self(
|
||||
k256::PublicKey::from_sec1_bytes(bytes).expect("Key is of valid size"),
|
||||
))
|
||||
} else {
|
||||
Err(CryptoError::InvalidKeySize)
|
||||
}
|
||||
Ok(Self(k256::PublicKey::from_sec1_bytes(bytes)?))
|
||||
}
|
||||
|
||||
/// Get the raw bytes of this `PublicKey`, which can be transferred to another party.
|
||||
///
|
||||
/// The public key is SEC-1 encoded and compressed.
|
||||
pub fn as_bytes(&self) -> Box<[u8]> {
|
||||
self.0.to_encoded_point(true).to_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
/// Export a public key and import it later
|
||||
#[test]
|
||||
fn import_public_key() {
|
||||
let kp = super::AsymmetricKeypair::new().expect("Can generate new keypair");
|
||||
let pk1 = kp.public_key();
|
||||
let pk_bytes = pk1.as_bytes();
|
||||
let pk2 = super::PublicKey::from_bytes(&pk_bytes).expect("Can import public key");
|
||||
|
||||
assert_eq!(pk1, pk2);
|
||||
}
|
||||
/// Make sure 2 random keypairs derive the same shared secret (and thus encryption key), by
|
||||
/// encrypting a random message, decrypting it, and verifying it matches.
|
||||
#[test]
|
||||
fn encrypt_and_decrypt() {
|
||||
let kp1 = super::AsymmetricKeypair::new().expect("Can generate new keypair");
|
||||
let kp2 = super::AsymmetricKeypair::new().expect("Can generate new keypair");
|
||||
|
||||
let pk1 = kp1.public_key();
|
||||
let pk2 = kp2.public_key();
|
||||
|
||||
let message = b"this is a random message to encrypt and decrypt";
|
||||
|
||||
let enc = kp1.encrypt(&pk2, message).expect("Can encrypt message");
|
||||
let dec = kp2.decrypt(&pk1, &enc).expect("Can decrypt message");
|
||||
|
||||
assert_eq!(message.as_slice(), dec.as_slice());
|
||||
}
|
||||
|
||||
/// Use a different public key for decrypting than the expected one, this should fail the
|
||||
/// decryption process as we use AEAD encryption with the symmetric key.
|
||||
#[test]
|
||||
fn decrypt_with_wrong_key() {
|
||||
let kp1 = super::AsymmetricKeypair::new().expect("Can generate new keypair");
|
||||
let kp2 = super::AsymmetricKeypair::new().expect("Can generate new keypair");
|
||||
let kp3 = super::AsymmetricKeypair::new().expect("Can generate new keypair");
|
||||
|
||||
let pk2 = kp2.public_key();
|
||||
let pk3 = kp3.public_key();
|
||||
|
||||
let message = b"this is a random message to encrypt and decrypt";
|
||||
|
||||
let enc = kp1.encrypt(&pk2, message).expect("Can encrypt message");
|
||||
let dec = kp2.decrypt(&pk3, &enc);
|
||||
|
||||
assert!(dec.is_err());
|
||||
}
|
||||
}
|
||||
|
@ -69,8 +69,8 @@ impl SymmetricKey {
|
||||
|
||||
// Extract nonce from the end of ciphertext
|
||||
let ciphertext_len = ciphertext.len() - NONCE_SIZE;
|
||||
let ciphertext = &ciphertext[0..ciphertext_len];
|
||||
let nonce_bytes = &ciphertext[ciphertext_len..];
|
||||
let ciphertext = &ciphertext[0..ciphertext_len];
|
||||
|
||||
// Create cipher
|
||||
let cipher = ChaCha20Poly1305::new_from_slice(&self.0)
|
||||
|
Loading…
Reference in New Issue
Block a user