aboutsummaryrefslogtreecommitdiff
path: root/core/src/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/crypto')
-rw-r--r--core/src/crypto/key_pair.rs142
-rw-r--r--core/src/crypto/mod.rs3
2 files changed, 145 insertions, 0 deletions
diff --git a/core/src/crypto/key_pair.rs b/core/src/crypto/key_pair.rs
new file mode 100644
index 0000000..899cb6a
--- /dev/null
+++ b/core/src/crypto/key_pair.rs
@@ -0,0 +1,142 @@
+use ed25519_dalek::{Signer as _, Verifier as _};
+use rand::rngs::OsRng;
+
+use crate::{error::Error, Result};
+
+/// key cryptography type
+pub enum KeyPairType {
+ Ed25519,
+}
+
+/// A Secret key
+pub struct SecretKey(Vec<u8>);
+
+#[derive(Clone)]
+pub enum KeyPair {
+ Ed25519(Ed25519KeyPair),
+}
+
+impl KeyPair {
+ /// Generate a new random keypair.
+ pub fn generate(kp_type: &KeyPairType) -> Self {
+ match kp_type {
+ KeyPairType::Ed25519 => Self::Ed25519(Ed25519KeyPair::generate()),
+ }
+ }
+
+ /// Sign a message using the private key.
+ pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
+ match self {
+ KeyPair::Ed25519(kp) => kp.sign(msg),
+ }
+ }
+
+ /// Get the public key of this keypair.
+ pub fn public(&self) -> PublicKey {
+ match self {
+ KeyPair::Ed25519(kp) => kp.public(),
+ }
+ }
+
+ /// Get the secret key of this keypair.
+ pub fn secret(&self) -> SecretKey {
+ match self {
+ KeyPair::Ed25519(kp) => kp.secret(),
+ }
+ }
+}
+
+/// An extension trait, adding essential methods to all [`KeyPair`] types.
+trait KeyPairExt {
+ /// Sign a message using the private key.
+ fn sign(&self, msg: &[u8]) -> Vec<u8>;
+
+ /// Get the public key of this keypair.
+ fn public(&self) -> PublicKey;
+
+ /// Get the secret key of this keypair.
+ fn secret(&self) -> SecretKey;
+}
+
+#[derive(Clone)]
+pub struct Ed25519KeyPair(ed25519_dalek::SigningKey);
+
+impl Ed25519KeyPair {
+ fn generate() -> Self {
+ Self(ed25519_dalek::SigningKey::generate(&mut OsRng))
+ }
+}
+
+impl KeyPairExt for Ed25519KeyPair {
+ fn sign(&self, msg: &[u8]) -> Vec<u8> {
+ self.0.sign(msg).to_bytes().to_vec()
+ }
+
+ fn public(&self) -> PublicKey {
+ PublicKey::Ed25519(Ed25519PublicKey(self.0.verifying_key()))
+ }
+
+ fn secret(&self) -> SecretKey {
+ SecretKey(self.0.to_bytes().to_vec())
+ }
+}
+
+pub enum PublicKey {
+ Ed25519(Ed25519PublicKey),
+}
+
+impl PublicKey {
+ pub fn from_bytes(kp_type: &KeyPairType, pk: &[u8]) -> Result<Self> {
+ match kp_type {
+ KeyPairType::Ed25519 => Ok(Self::Ed25519(Ed25519PublicKey::from_bytes(pk)?)),
+ }
+ }
+
+ pub fn as_bytes(&self) -> &[u8] {
+ match self {
+ Self::Ed25519(pk) => pk.as_bytes(),
+ }
+ }
+
+ /// Verify a signature on a message with this public key.
+ pub fn verify(&self, msg: &[u8], signature: &[u8]) -> Result<()> {
+ match self {
+ Self::Ed25519(pk) => pk.verify(msg, signature),
+ }
+ }
+}
+
+/// An extension trait, adding essential methods to all [`PublicKey`] types.
+trait PublicKeyExt {
+ fn as_bytes(&self) -> &[u8];
+
+ /// Verify a signature on a message with this public key.
+ fn verify(&self, msg: &[u8], signature: &[u8]) -> Result<()>;
+}
+
+pub struct Ed25519PublicKey(ed25519_dalek::VerifyingKey);
+
+impl Ed25519PublicKey {
+ pub fn from_bytes(pk: &[u8]) -> Result<Self> {
+ let pk_bytes: [u8; 32] = pk
+ .try_into()
+ .map_err(|_| Error::TryInto("Failed to convert slice to [u8; 32]"))?;
+
+ Ok(Self(ed25519_dalek::VerifyingKey::from_bytes(&pk_bytes)?))
+ }
+}
+
+impl PublicKeyExt for Ed25519PublicKey {
+ fn as_bytes(&self) -> &[u8] {
+ self.0.as_bytes()
+ }
+
+ fn verify(&self, msg: &[u8], signature: &[u8]) -> Result<()> {
+ let sig_bytes: [u8; 64] = signature
+ .try_into()
+ .map_err(|_| Error::TryInto("Failed to convert slice to [u8; 64]"))?;
+ self.0
+ .verify(msg, &ed25519_dalek::Signature::from_bytes(&sig_bytes))?;
+ Ok(())
+ }
+}
diff --git a/core/src/crypto/mod.rs b/core/src/crypto/mod.rs
new file mode 100644
index 0000000..7d56e69
--- /dev/null
+++ b/core/src/crypto/mod.rs
@@ -0,0 +1,3 @@
+mod key_pair;
+
+pub use key_pair::{KeyPair, KeyPairType, PublicKey, SecretKey};