Selaa lähdekoodia

Got the block sign and verify test to pass.

Matthew Carr 2 vuotta sitten
vanhempi
commit
734eae4778
2 muutettua tiedostoa jossa 164 lisäystä ja 15 poistoa
  1. 131 10
      crates/node/src/crypto.rs
  2. 33 5
      crates/node/src/test_helpers.rs

+ 131 - 10
crates/node/src/crypto.rs

@@ -30,6 +30,7 @@ pub enum Error {
     NoKeyAvailable,
     MissingPrivateKey,
     KeyVariantUnsupported,
+    BlockNotEncrypted,
     Message(String),
     Serde(serde_block_tree::Error),
 }
@@ -56,11 +57,37 @@ pub enum Hash {
     Sha2_512([u8; 64]),
 }
 
+const RSA_SIG_LEN: usize = 512;
+
 /// A cryptographic signature.
 #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
 pub enum Signature {
     #[serde(with = "BigArray")]
-    Rsa([u8; 64]),
+    Rsa([u8; RSA_SIG_LEN]),
+}
+
+pub enum SignatureId {
+    Rsa
+}
+
+impl Signature {
+    fn new(id: SignatureId) -> Signature {
+        match id {
+            SignatureId::Rsa => Signature::Rsa([0; RSA_SIG_LEN])
+        }
+    }
+
+    fn as_slice(&self) -> &[u8] {
+        match self {
+            Signature::Rsa(buf) => buf.as_slice()
+        }
+    }
+
+    fn as_mut_slice(&mut self) -> &mut [u8] {
+        match self {
+            Signature::Rsa(buf) => buf.as_mut_slice()
+        }
+    }
 }
 
 /// Identifies a type of cryptographic key. The variants of this enum match those of `Key`.
@@ -273,13 +300,17 @@ impl<'a> TryFrom<&'a Key> for DecryptionAlgo<'a> {
 struct SignAlgo {
     key: PKey<Private>,
     digest: MessageDigest,
+    signature: Signature
 }
 
 impl SignAlgo {
-    fn sign(&self, slice: &[u8]) -> Result<Vec<u8>> {
+    fn sign(&mut self, header: &[u8], body: &[u8]) -> Result<()> {
         let mut signer = Signer::new(self.digest, &self.key).map_err(Error::from)?;
-        signer.update(slice).map_err(Error::from)?;
-        signer.sign_to_vec().map_err(Error::from)
+        signer.update(header).map_err(Error::from)?;
+        signer.update(body).map_err(Error::from)?;
+        let buf = self.signature.as_mut_slice();
+        signer.sign(buf).map_err(Error::from)?;
+        Ok(())
     }
 }
 
@@ -291,7 +322,8 @@ impl TryFrom<&Key> for SignAlgo {
                 let rsa = Rsa::private_key_from_der(private.as_slice()).map_err(Error::from)?;
                 Ok(SignAlgo {
                     key: PKey::from_rsa(rsa).map_err(Error::from)?,
-                    digest: MessageDigest::sha256()
+                    digest: MessageDigest::sha256(),
+                    signature: Signature::new(SignatureId::Rsa)
                 })
             },
             _ => Err(Error::KeyVariantUnsupported)
@@ -305,9 +337,10 @@ struct VerifyAlgo {
 }
 
 impl VerifyAlgo {
-    fn verify(&self, slice: &[u8], signature: &[u8]) -> Result<bool> {
+    fn verify(&self, header: &[u8], body: &[u8], signature: &[u8]) -> Result<bool> {
         let mut verifier = Verifier::new(self.digest, &self.key).map_err(Error::from)?;
-        verifier.update(slice).map_err(Error::from)?;
+        verifier.update(header).map_err(Error::from)?;
+        verifier.update(body).map_err(Error::from)?;
         verifier.verify(signature).map_err(Error::from)
     }
 }
@@ -387,6 +420,55 @@ fn decrypt_slice(ciphertext: &[u8], key: &Key) -> Result<Vec<u8>> {
     algo.decrypt(ciphertext)
 }
 
+#[derive(Serialize)]
+struct SigHeader<'a> {
+    path: &'a Path,
+    read_caps: &'a HashMap<Principal, Cryptotext<Key>>,
+    write_cap: &'a WriteCap,
+}
+
+impl<'a> From<&'a Block> for SigHeader<'a> {
+    fn from(block: &'a Block) -> SigHeader<'a> {
+        SigHeader {
+            path: &block.path,
+            read_caps: &block.read_caps,
+            write_cap: &block.write_cap,
+        }
+    }
+}
+
+fn get_body(block: &Block) -> Result<&[u8]> {
+    let body = match &block.body {
+        Cryptotext::Cipher(body) => body,
+        Cryptotext::Plain(_) => {
+            return Err(Error::BlockNotEncrypted);
+        }
+    };
+    Ok(body)
+}
+
+pub(crate) fn sign_block(versioned_block: &mut VersionedBlock, write_cap: WriteCap) -> Result<()> {
+    let VersionedBlock::V0(block) = versioned_block;
+    block.write_cap = write_cap;
+    let body = get_body(block)?;
+    let sig_header = SigHeader::from(&*block);
+    let header = to_vec(&sig_header)?;
+    let mut sign_algo = SignAlgo::try_from(&block.write_cap.signing_key)?;
+    sign_algo.sign(header.as_slice(), body)?;
+    block.signature = sign_algo.signature;
+    Ok(())
+}
+
+pub(crate) fn verify_block(versioned_block: &VersionedBlock) -> Result<bool> {
+    let VersionedBlock::V0(block) = versioned_block;
+    let body = get_body(block)?;
+    let sig_header = SigHeader::from(&*block);
+    let header = to_vec(&sig_header)?;
+    let verify_algo = VerifyAlgo::try_from(&block.write_cap.signing_key)?;
+    // TODO: Verify the chain in the write cap.
+    verify_algo.verify(header.as_slice(), body, block.signature.as_slice())
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -454,15 +536,38 @@ mod tests {
     #[test]
     fn rsa_sign_and_verify() -> Result<()> {
         let key = Key::generate(KeyId::Rsa)?;
+        let header = b"About: lyrics";
         let message = b"Everything that feels so good is bad bad bad.";
-        let signer = SignAlgo::try_from(&key)?;
-        let signature = signer.sign(message)?;
+        let mut signer = SignAlgo::try_from(&key)?;
+        signer.sign(header, message)?;
         let verifier = VerifyAlgo::try_from(&key)?;
-        let verified = verifier.verify(message, signature.as_slice())?;
+        let verified = verifier.verify(header, message, signer.signature.as_slice())?;
         assert_eq!(true, verified);
         Ok(())
     }
 
+    #[test]
+    fn sign_verify_block_rsa() -> Result<()> {
+        let principal = make_principal();
+        let block_key = Key::Aes256Ctr { key: BLOCK_KEY, iv: BLOCK_IV };
+        let mut block = make_versioned_block(principal.clone(), block_key)?;
+        let key = Key::generate(KeyId::Rsa)?;
+        let write_cap = WriteCap {
+            issued_to: Principal(Hash::Sha2_256(PRINCIPAL)),
+            issued_by: Principal(Hash::Sha2_256(PRINCIPAL)),
+            path: Path::try_from("contacts/emergency")
+                .map_err(|err| Error::Message(err.to_string()))?,
+            expires: Epoch(1649904316),
+            signing_key: key,
+            signature: Signature::Rsa(SIGNATURE),
+            next: None,
+        };
+        block = encrypt_block(block, &principal, &write_cap.signing_key)?;
+        sign_block(&mut block, write_cap)?;
+        assert_eq!(true, verify_block(&block)?);
+        Ok(())
+    }
+
     /// Tests that validate the dependencies of this module.
     mod dependency_tests {
         use super::*;
@@ -507,5 +612,21 @@ mod tests {
             assert_eq!(44, public_len);
             assert_eq!(48, private_len);
         }
+
+        #[test]
+        fn rsa_signature_len() -> Result<()> {
+            use openssl::rsa::Rsa;
+            let key = Key::generate(KeyId::Rsa)?;
+            let sign_algo = SignAlgo::try_from(&key)?;
+            let private = match &key {
+                Key::Rsa { private: Some(private), .. } => private,
+                _ => return Err(Error::Message("Incorrect key returned.".to_string()))
+            };
+            let rsa = Rsa::private_key_from_der(private)?;
+            let pkey = PKey::from_rsa(rsa)?;
+            let signer = Signer::new(sign_algo.digest, &pkey)?;
+            assert_eq!(RSA_SIG_LEN, signer.len()?);
+            Ok(())
+        }
     }
 }

+ 33 - 5
crates/node/src/test_helpers.rs

@@ -20,11 +20,39 @@ pub const PAYLOAD: [u8; 128] = [
     0xEE, 0x1F, 0x84, 0x17, 0xA2, 0x74, 0xC3, 0xC3, 0xD5, 0x2F, 0x70, 0x74, 0xFE, 0xD8, 0x2C, 0x29,
 ];
 
-pub const SIGNATURE: [u8; 64] = [
-    0x2E, 0x19, 0x8E, 0xCC, 0x2D, 0xE1, 0x0E, 0x42, 0x3F, 0xBB, 0x89, 0x3D, 0x07, 0xAB, 0x57, 0xBF,
-    0xEB, 0xB1, 0xA7, 0x23, 0xF9, 0xD2, 0xC3, 0x3F, 0x7A, 0x3C, 0xD0, 0x31, 0x38, 0x01, 0x33, 0x1F,
-    0x07, 0x8D, 0x68, 0x0C, 0x6B, 0xF1, 0xBA, 0xD3, 0xD4, 0xAE, 0xAD, 0x1A, 0xF7, 0x5D, 0x2C, 0xEF,
-    0x1F, 0x5C, 0x50, 0xE9, 0xFA, 0x8A, 0xDB, 0xB2, 0x4C, 0xC6, 0x9B, 0x06, 0x5F, 0xFB, 0xE3, 0xDA,
+pub const SIGNATURE: [u8; 512] = [
+    0x12, 0xB1, 0x09, 0x2F, 0x2B, 0x3C, 0x53, 0xE8, 0x1B, 0x2B, 0x6A, 0xE7, 0x97, 0x42, 0x9D, 0x83,
+    0x71, 0x75, 0x65, 0x25, 0xFD, 0xB0, 0x0E, 0x2F, 0xAB, 0x53, 0xB7, 0x03, 0x03, 0x39, 0xEE, 0xE9,
+    0x15, 0x19, 0xAB, 0x1A, 0xF1, 0x2C, 0x3C, 0xAB, 0x5C, 0x02, 0xEA, 0xD6, 0xF6, 0x94, 0x36, 0x80,
+    0x5F, 0xD1, 0x8E, 0xC4, 0xB9, 0xB5, 0x04, 0x73, 0xBB, 0x77, 0x2C, 0x9C, 0xAF, 0xE6, 0x38, 0xB7,
+    0xD8, 0xC1, 0xA3, 0x1B, 0xAD, 0xFB, 0xB2, 0x5E, 0x77, 0xBD, 0x79, 0xDC, 0x4E, 0xEC, 0xEA, 0xFA,
+    0x80, 0x9F, 0x12, 0x60, 0xC4, 0xB3, 0x71, 0xAF, 0x1C, 0x28, 0xEE, 0x91, 0x1D, 0x6A, 0x69, 0x31,
+    0xA4, 0x5A, 0xAA, 0xBE, 0x0B, 0x20, 0x6A, 0xE1, 0x61, 0x0E, 0x0B, 0x9F, 0x60, 0x73, 0xBE, 0x29,
+    0x1F, 0x11, 0x0A, 0x8F, 0x42, 0x8F, 0x80, 0xC1, 0x06, 0x40, 0x29, 0xE9, 0xF1, 0x74, 0x44, 0x69,
+    0xCC, 0xD3, 0x05, 0x22, 0x24, 0x87, 0x94, 0x49, 0x4B, 0x5B, 0x62, 0x48, 0x01, 0x7B, 0x05, 0x28,
+    0xBE, 0x4D, 0x50, 0x06, 0xE5, 0x67, 0xA8, 0xFB, 0x9A, 0x19, 0x52, 0x57, 0x4B, 0xC4, 0xBB, 0x6A,
+    0xF5, 0x0D, 0x67, 0xD0, 0x08, 0x93, 0x81, 0xD2, 0x9E, 0xE2, 0xC8, 0xFA, 0x25, 0xEE, 0x9D, 0xC5,
+    0xD8, 0xF4, 0xD5, 0x17, 0xE4, 0xEF, 0xFC, 0x09, 0xB0, 0x09, 0xCA, 0xCA, 0x71, 0x36, 0x61, 0xBE,
+    0xC1, 0xD0, 0x53, 0x6D, 0x0C, 0x0A, 0x4D, 0xF1, 0xE0, 0xAB, 0x2C, 0x89, 0x98, 0x81, 0xED, 0x25,
+    0xF8, 0x81, 0x8E, 0x2C, 0x46, 0x74, 0x57, 0xCF, 0x5B, 0xE2, 0x14, 0xA5, 0xBF, 0x56, 0xED, 0xD3,
+    0x11, 0xE7, 0xB4, 0x8D, 0x89, 0x3A, 0xB2, 0x78, 0xF1, 0xA9, 0x82, 0x9D, 0x3B, 0xE5, 0x6B, 0xD2,
+    0xA5, 0xB6, 0xFB, 0x71, 0x0F, 0x98, 0x52, 0x54, 0x1E, 0x98, 0xD2, 0x3B, 0x78, 0x51, 0xD1, 0xE2,
+    0x57, 0xAE, 0xB3, 0x34, 0x0E, 0x20, 0x26, 0xCF, 0x4B, 0x1F, 0x12, 0xCA, 0xB1, 0xD5, 0x67, 0x55,
+    0xF9, 0xE2, 0xA9, 0x7B, 0xAE, 0x35, 0x35, 0x67, 0xA3, 0xCA, 0xBD, 0xF2, 0x41, 0x4E, 0x3F, 0x7E,
+    0x20, 0x72, 0xC2, 0xCC, 0xE4, 0x90, 0x00, 0x04, 0x5D, 0xF7, 0xD9, 0xC7, 0x0C, 0x2C, 0xF8, 0x80,
+    0xCB, 0xF2, 0x3E, 0x1A, 0xE9, 0x43, 0x23, 0xAF, 0x62, 0x57, 0xD1, 0x4C, 0xFD, 0x05, 0xB6, 0xB6,
+    0x86, 0xB9, 0x86, 0x40, 0xC2, 0x56, 0x45, 0x52, 0xE2, 0x93, 0x62, 0x65, 0x23, 0xE7, 0x1D, 0x89,
+    0xCA, 0x40, 0x23, 0x44, 0xDB, 0x56, 0x90, 0x4A, 0x0E, 0xB1, 0xB1, 0xE1, 0x9B, 0x5A, 0x5D, 0x53,
+    0xEF, 0x4E, 0xE1, 0x0E, 0x12, 0xA9, 0x7C, 0x11, 0x0B, 0x6A, 0x4C, 0x3A, 0x8F, 0x2B, 0x9F, 0xC6,
+    0x42, 0xD7, 0xFE, 0x7D, 0x10, 0x02, 0xBD, 0x31, 0x21, 0xCD, 0xD1, 0x32, 0x04, 0x22, 0xE2, 0x36,
+    0x88, 0x8F, 0xA3, 0xFF, 0x5C, 0x81, 0xE2, 0xDA, 0xAF, 0x39, 0x10, 0x2B, 0x15, 0xDB, 0x66, 0x52,
+    0xF6, 0x8A, 0xAE, 0x37, 0xA7, 0x6E, 0x6F, 0xEA, 0xBC, 0xD0, 0x89, 0xA1, 0x05, 0x35, 0x4B, 0xD3,
+    0x18, 0xDA, 0xBC, 0xA0, 0x89, 0x22, 0xA9, 0x9A, 0xC8, 0x08, 0xD4, 0xDF, 0x13, 0x49, 0xC8, 0xE7,
+    0x2F, 0x7E, 0x7C, 0x7B, 0x02, 0x09, 0x2A, 0xCA, 0x13, 0x0E, 0xB5, 0x29, 0xC9, 0xA2, 0xD5, 0x55,
+    0x45, 0x73, 0x95, 0xC2, 0x7F, 0xFA, 0x33, 0x44, 0xF0, 0xE2, 0x32, 0x5E, 0x5B, 0x89, 0x0C, 0x7C,
+    0xC5, 0x59, 0xAB, 0x74, 0x29, 0xBE, 0x3B, 0x3D, 0xB8, 0xB3, 0x93, 0x4B, 0x49, 0xDE, 0xE7, 0x5F,
+    0x0F, 0x48, 0x23, 0x9E, 0x08, 0xDF, 0x23, 0x9E, 0xB8, 0x48, 0xB8, 0xB1, 0x8D, 0xBD, 0x66, 0xA0,
+    0x24, 0xAB, 0x4D, 0xC2, 0xDE, 0x6A, 0x1E, 0x76, 0x42, 0x0D, 0x36, 0x9D, 0xA4, 0xA2, 0x43, 0xC2,
 ];
 
 pub const KEY: [u8; 32] = [