summaryrefslogtreecommitdiffstats
path: root/crypto/src/keys.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/keys.rs')
-rw-r--r--crypto/src/keys.rs84
1 files changed, 84 insertions, 0 deletions
diff --git a/crypto/src/keys.rs b/crypto/src/keys.rs
new file mode 100644
index 0000000..4666476
--- /dev/null
+++ b/crypto/src/keys.rs
@@ -0,0 +1,84 @@
+use ed25519_dalek::{Signer, Verifier};
+use serde::{Deserialize, Serialize};
+
+/// Public key wrapper
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
+pub struct PublicKey(pub [u8; 32]);
+
+/// Secret key wrapper
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct SecretKey(pub [u8; 32]);
+
+/// Key pair for signing
+#[derive(Debug, Clone)]
+pub struct KeyPair {
+ pub public: PublicKey,
+ pub secret: SecretKey,
+ signing_key: ed25519_dalek::SigningKey,
+}
+
+impl KeyPair {
+ /// Generate new random keypair
+ pub fn generate() -> Self {
+ use rand::RngCore;
+ let mut rng = rand::thread_rng();
+ let mut secret_bytes = [0u8; 32];
+ rng.fill_bytes(&mut secret_bytes);
+
+ let signing_key = ed25519_dalek::SigningKey::from_bytes(&secret_bytes);
+ let verifying_key = signing_key.verifying_key();
+
+ Self {
+ public: PublicKey(verifying_key.to_bytes()),
+ secret: SecretKey(signing_key.to_bytes()),
+ signing_key,
+ }
+ }
+
+ /// Sign a message
+ pub fn sign(&self, message: &[u8]) -> [u8; 64] {
+ self.signing_key.sign(message).to_bytes()
+ }
+
+ /// Verify a signature
+ pub fn verify(public_key: &PublicKey, message: &[u8], signature: &[u8; 64]) -> bool {
+ let verifying_key = match ed25519_dalek::VerifyingKey::from_bytes(&public_key.0) {
+ Ok(key) => key,
+ Err(_) => return false,
+ };
+
+ let sig = ed25519_dalek::Signature::from_bytes(signature);
+
+ verifying_key.verify(message, &sig).is_ok()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_keypair_generation() {
+ let keypair = KeyPair::generate();
+ assert_ne!(keypair.public.0, [0u8; 32]);
+ assert_ne!(keypair.secret.0, [0u8; 32]);
+ }
+
+ #[test]
+ fn test_sign_verify() {
+ let keypair = KeyPair::generate();
+ let message = b"Hello, OnionCoin!";
+
+ let signature = keypair.sign(message);
+ assert!(KeyPair::verify(&keypair.public, message, &signature));
+ }
+
+ #[test]
+ fn test_verify_invalid_signature() {
+ let keypair = KeyPair::generate();
+ let message = b"Hello, OnionCoin!";
+ let wrong_sig = [0u8; 64];
+
+ assert!(!KeyPair::verify(&keypair.public, message, &wrong_sig));
+ }
+}