EXPERIMENTAL: change derive_key() to use const generics
diff --git a/b3sum/tests/cli_tests.rs b/b3sum/tests/cli_tests.rs
index 51fbbba..8d35b17 100644
--- a/b3sum/tests/cli_tests.rs
+++ b/b3sum/tests/cli_tests.rs
@@ -121,8 +121,7 @@
     let f = tempfile::NamedTempFile::new().unwrap();
     f.as_file().write_all(b"key material").unwrap();
     f.as_file().flush().unwrap();
-    let mut derive_key_out = [0; blake3::OUT_LEN];
-    blake3::derive_key(context, b"key material", &mut derive_key_out);
+    let derive_key_out: [u8; blake3::OUT_LEN] = blake3::derive_key(context, b"key material");
     let expected = hex::encode(&derive_key_out);
     let output = cmd!(b3sum_exe(), "--derive-key", context, "--no-names", f.path())
         .read()
diff --git a/src/lib.rs b/src/lib.rs
index e5f3eb6..64292c6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -841,11 +841,13 @@
 /// [`Hasher::finalize_xof`]: struct.Hasher.html#method.finalize_xof
 /// [Argon2]: https://en.wikipedia.org/wiki/Argon2
 /// [`Hasher::update_with_join`]: struct.Hasher.html#method.update_with_join
-pub fn derive_key(context: &str, key_material: &[u8], output: &mut [u8]) {
+pub fn derive_key<const N: usize>(context: &str, key_material: &[u8]) -> [u8; N] {
     let context_key = hash_all_at_once(context.as_bytes(), IV, DERIVE_KEY_CONTEXT).root_hash();
     let context_key_words = platform::words_from_le_bytes_32(context_key.as_bytes());
     let inner_output = hash_all_at_once(key_material, &context_key_words, DERIVE_KEY_MATERIAL);
-    OutputReader::new(inner_output).fill(output);
+    let mut ret = [0; N];
+    OutputReader::new(inner_output).fill(&mut ret);
+    ret
 }
 
 fn parent_node_output(
diff --git a/src/test.rs b/src/test.rs
index cd46091..c0f327f 100644
--- a/src/test.rs
+++ b/src/test.rs
@@ -326,9 +326,8 @@
             reference_hasher.finalize(&mut expected_out);
 
             // all at once
-            let mut test_out = [0; OUT];
-            crate::derive_key(context, input, &mut test_out);
-            assert_eq!(test_out[..], expected_out[..]);
+            let test_out = crate::derive_key(context, input);
+            assert_eq!(test_out, expected_out);
             // incremental
             let mut hasher = crate::Hasher::new_derive_key(context);
             hasher.update(input);
@@ -501,8 +500,7 @@
     kdf.update(&[42; 3 * CHUNK_LEN + 7]);
     kdf.reset();
     kdf.update(&[42; CHUNK_LEN + 3]);
-    let mut expected = [0; crate::OUT_LEN];
-    crate::derive_key(context, &[42; CHUNK_LEN + 3], &mut expected);
+    let expected = crate::derive_key(context, &[42; CHUNK_LEN + 3]);
     assert_eq!(kdf.finalize(), expected);
 }
 
diff --git a/test_vectors/src/lib.rs b/test_vectors/src/lib.rs
index 04460f6..02ba167 100644
--- a/test_vectors/src/lib.rs
+++ b/test_vectors/src/lib.rs
@@ -278,9 +278,8 @@
             &expected_keyed_hash[..32],
             &blake3::keyed_hash(key, input).as_bytes()[..],
         );
-        let mut derive_key_out = vec![0; expected_derive_key.len()];
-        blake3::derive_key(TEST_CONTEXT, input, &mut derive_key_out);
-        assert_eq!(expected_derive_key, &derive_key_out[..],);
+        let derive_key_output: [u8; OUTPUT_LEN] = blake3::derive_key(TEST_CONTEXT, input);
+        assert_eq!(expected_derive_key, &derive_key_output[..],);
     }
 
     #[test]