Repository: aws/aws-lc-rs (language: rust)

Issue:
Add `Ed25519KeyPair::generate(&rng)` function
### Problem:

An `Ed25519KeyPair` can't be generated without serializing it first, which is a bit awkward. E.g.

``` rust
use aws_lc_rs::signature::Ed25519KeyPair;

let rng = rand::SystemRandom::new();
let bytes = Ed25519KeyPair::generate_pkcs8v1(&rng).unwrap();
let signing_key_pair = Ed25519KeyPair::from_pkcs8_maybe_unchecked(bytes.as_ref()).unwrap();
```

### Solution:

There should be a `Ed25519KeyPair::generate()` much like there is a `EcdsaKeyPair::generate()`. E.g.

``` rust
use aws_lc_rs::signature::Ed25519KeyPair;

let rng = rand::SystemRandom::new();
let signing_key_pair = Ed25519KeyPair::generate(&rng).unwrap();
```



Discussion / hints:

Fix patch:
diff --git a/aws-lc-rs/src/ed25519.rs b/aws-lc-rs/src/ed25519.rs
index c71c6ca43dd..867cc7f5b1b 100644
--- a/aws-lc-rs/src/ed25519.rs
+++ b/aws-lc-rs/src/ed25519.rs
@@ -244,6 +244,31 @@ pub(crate) fn generate_key() -> Result<LcPtr<EVP_PKEY>, ()> {
 }
 
 impl Ed25519KeyPair {
+    /// Generates a new key pair and returns the key pair.
+    ///
+    /// # Errors
+    /// `error::Unspecified` if key generation fails.
+    pub fn generate() -> Result<Self, Unspecified> {
+        let evp_pkey = generate_key()?;
+
+        let mut public_key = [0u8; ED25519_PUBLIC_KEY_LEN];
+        let mut out_len: usize = ED25519_PUBLIC_KEY_LEN;
+        if 1 != unsafe {
+            EVP_PKEY_get_raw_public_key(*evp_pkey.as_const(), public_key.as_mut_ptr(), &mut out_len)
+        } {
+            return Err(Unspecified);
+        }
+        debug_assert_eq!(public_key.len(), out_len);
+
+        Ok(Self {
+            public_key: PublicKey {
+                public_key_bytes: public_key,
+                evp_pkey: evp_pkey.clone(),
+            },
+            evp_pkey,
+        })
+    }
+
     /// Generates a new key pair and returns the key pair serialized as a
     /// PKCS#8 document.
     ///
@@ -527,9 +552,21 @@ mod tests {
     use crate::ed25519::Ed25519KeyPair;
     use crate::encoding::{AsBigEndian, AsDer, Pkcs8V1Der, Pkcs8V2Der, PublicKeyX509Der};
     use crate::rand::SystemRandom;
-    use crate::signature::KeyPair;
+    use crate::signature::{KeyPair, UnparsedPublicKey, ED25519};
     use crate::{hex, test};
 
+    #[test]
+    fn test_generate() {
+        const MESSAGE: &[u8] = b"test message";
+        let key_pair = Ed25519KeyPair::generate().unwrap();
+        let public_key = key_pair.public_key();
+        let signature = key_pair.sign(MESSAGE);
+        let unparsed_public_key = UnparsedPublicKey::new(&ED25519, public_key.as_ref());
+        let _ = unparsed_public_key
+            .verify(MESSAGE, signature.as_ref())
+            .unwrap();
+    }
+
     #[test]
     fn test_generate_pkcs8() {
         let rng = SystemRandom::new();


Test patch: