Add Ed25519 PKCS#8 support.
This commit is contained in:
parent
743cefca51
commit
eacd3b8fa0
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
//! EdDSA Signatures.
|
//! EdDSA Signatures.
|
||||||
|
|
||||||
use {digest, error, private, rand, signature};
|
use {digest, error, pkcs8, private, rand, signature};
|
||||||
use super::ops::*;
|
use super::ops::*;
|
||||||
use untrusted;
|
use untrusted;
|
||||||
|
|
||||||
@ -33,54 +33,95 @@ pub struct Ed25519KeyPair {
|
|||||||
public_key: PublicKey,
|
public_key: PublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The raw bytes of the Ed25519 key pair, for serialization.
|
|
||||||
pub struct Ed25519KeyPairBytes {
|
|
||||||
/// Private key (seed) bytes.
|
|
||||||
pub private_key: [u8; SEED_LEN],
|
|
||||||
|
|
||||||
/// Public key bytes.
|
|
||||||
pub public_key: [u8; PUBLIC_KEY_LEN],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Ed25519KeyPair {
|
impl<'a> Ed25519KeyPair {
|
||||||
/// Generates a new random key pair. There is no way to extract the private
|
/// Generates a new random key pair. There is no way to extract the private
|
||||||
/// key bytes to save them. If you need to save the private key bytes for
|
/// key bytes to save them. If you need to save the private key bytes for
|
||||||
/// future use then use `generate_serializable()` instead.
|
/// future use then use `generate_serializable()` instead.
|
||||||
pub fn generate(rng: &rand::SecureRandom)
|
pub fn generate(rng: &rand::SecureRandom)
|
||||||
-> Result<Ed25519KeyPair, error::Unspecified> {
|
-> Result<Ed25519KeyPair, error::Unspecified> {
|
||||||
Ed25519KeyPair::generate_serializable(rng).map(|(key_pair, _)| key_pair)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates a new key pair and returns the key pair as both an
|
|
||||||
/// `Ed25519KeyPair` and a `Ed25519KeyPairBytes`. There is no way to
|
|
||||||
/// extract the private key bytes from an `Ed25519KeyPair`, so extracting
|
|
||||||
/// the values from the `Ed25519KeyPairBytes` is the only way to get them.
|
|
||||||
pub fn generate_serializable(rng: &rand::SecureRandom)
|
|
||||||
-> Result<(Ed25519KeyPair, Ed25519KeyPairBytes),
|
|
||||||
error::Unspecified> {
|
|
||||||
let mut seed = [0u8; SEED_LEN];
|
let mut seed = [0u8; SEED_LEN];
|
||||||
try!(rng.fill(&mut seed));
|
try!(rng.fill(&mut seed));
|
||||||
|
Ok(Ed25519KeyPair::from_seed_(&seed))
|
||||||
let key_pair = Self::from_seed_(&seed);
|
|
||||||
let bytes = Ed25519KeyPairBytes {
|
|
||||||
private_key: seed,
|
|
||||||
public_key: key_pair.public_key,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((key_pair, bytes))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copies key data from the given slices to create a new key pair. The
|
/// Generates a new key pair and returns the key pair serialized as a
|
||||||
/// first slice must hold the private key and the second slice must hold
|
/// PKCS#8 document.
|
||||||
/// the public key. Both slices must contain 32 little-endian-encoded
|
|
||||||
/// bytes.
|
|
||||||
///
|
///
|
||||||
/// This is intended for use by code that deserializes key pairs.
|
/// The PKCS#8 document will be a v2 `OneAsymmetricKey` with the public key,
|
||||||
|
/// as described in [RFC 5958 Section 2]. See also
|
||||||
|
/// https://tools.ietf.org/html/draft-ietf-curdle-pkix-04.
|
||||||
///
|
///
|
||||||
/// The private and public keys will be verified to be consistent. This
|
/// [RFC 5958 Section 2]: https://tools.ietf.org/html/rfc5958#section-2
|
||||||
/// helps protect, for example, against the accidental swapping of the
|
pub fn generate_pkcs8(rng: &rand::SecureRandom)
|
||||||
/// public and private components of the key pair. This also detects
|
-> Result<[u8; ED25519_PKCS8_V2_LEN], error::Unspecified> {
|
||||||
/// corruption that might have occurred during storage of the key pair.
|
let mut seed = [0u8; SEED_LEN];
|
||||||
|
try!(rng.fill(&mut seed));
|
||||||
|
let key_pair = Ed25519KeyPair::from_seed_(&seed);
|
||||||
|
|
||||||
|
let mut bytes = [0; ED25519_PKCS8_V2_LEN];
|
||||||
|
let (before_seed, after_seed) =
|
||||||
|
PKCS8_TEMPLATE.split_at(PKCS8_SEED_INDEX);
|
||||||
|
bytes[..PKCS8_SEED_INDEX].copy_from_slice(before_seed);
|
||||||
|
bytes[PKCS8_SEED_INDEX..(PKCS8_SEED_INDEX + SEED_LEN)]
|
||||||
|
.copy_from_slice(&seed);
|
||||||
|
bytes[(PKCS8_SEED_INDEX + SEED_LEN)..PKCS8_PUBLIC_KEY_INDEX]
|
||||||
|
.copy_from_slice(after_seed);
|
||||||
|
bytes[PKCS8_PUBLIC_KEY_INDEX..]
|
||||||
|
.copy_from_slice(key_pair.public_key_bytes());
|
||||||
|
|
||||||
|
Ok(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses a PKCS#8 v2 Ed25519 private key.
|
||||||
|
///
|
||||||
|
/// The input must be in PKCS#8 v2 format, and in particular it must contain
|
||||||
|
/// the public key in addition to the private key. `from_pkcs8()` will
|
||||||
|
/// verify that the public key and the private key are consistent with each
|
||||||
|
/// other.
|
||||||
|
///
|
||||||
|
/// If you need to parse PKCS#8 v1 files (without the public key) then use
|
||||||
|
/// `Ed25519KeyPair::from_pkcs8_maybe_unchecked()` instead.
|
||||||
|
pub fn from_pkcs8(input: untrusted::Input)
|
||||||
|
-> Result<Ed25519KeyPair, error::Unspecified> {
|
||||||
|
let (seed, public_key) =
|
||||||
|
try!(pkcs8::unwrap_key(pkcs8::Version::V2Only, input,
|
||||||
|
ed25519_alg_id()));
|
||||||
|
Self::from_seed_and_public_key(seed, public_key.unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parses a PKCS#8 v1 or v2 Ed25519 private key.
|
||||||
|
///
|
||||||
|
/// It is recommended to use `Ed25519KeyPair::from_pkcs8()`, which accepts
|
||||||
|
/// only PKCS#8 v2 files that contain the public key.
|
||||||
|
/// `from_pkcs8_maybe_unchecked()` parses PKCS#2 files exactly like
|
||||||
|
/// `from_pkcs8()`. It also accepts v1 files. PKCS#8 v1 files do not contain
|
||||||
|
/// the public key, so when a v1 file is parsed the public key will be
|
||||||
|
/// computed from the private key, and there will be no consistency check
|
||||||
|
/// between the public key and the private key.
|
||||||
|
///
|
||||||
|
/// PKCS#8 v2 files are parsed exactly like `Ed25519KeyPair::from_pkcs8()`.
|
||||||
|
pub fn from_pkcs8_maybe_unchecked(input: untrusted::Input)
|
||||||
|
-> Result<Ed25519KeyPair, error::Unspecified> {
|
||||||
|
let (seed, public_key) =
|
||||||
|
try!(pkcs8::unwrap_key(pkcs8::Version::V1OrV2, input,
|
||||||
|
ed25519_alg_id()));
|
||||||
|
if let Some(public_key) = public_key {
|
||||||
|
Self::from_seed_and_public_key(seed, public_key)
|
||||||
|
} else {
|
||||||
|
Self::from_seed_unchecked(seed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructs a Ed25519 key pair from the private key seed `seed` and its
|
||||||
|
/// public key `public_key`.
|
||||||
|
///
|
||||||
|
/// It is recommended to use `Ed25519KeysiPair::from_pkcs8()` instead.
|
||||||
|
///
|
||||||
|
/// The private and public keys will be verified to be consistent with each
|
||||||
|
/// other. This helps avoid misuse of the key (e.g. accidentally swapping
|
||||||
|
/// the private key and public key, or using the wrong private key for the
|
||||||
|
/// public key). This also detects any corruption of the public or private
|
||||||
|
/// key.
|
||||||
pub fn from_seed_and_public_key(seed: untrusted::Input,
|
pub fn from_seed_and_public_key(seed: untrusted::Input,
|
||||||
public_key: untrusted::Input)
|
public_key: untrusted::Input)
|
||||||
-> Result<Ed25519KeyPair, error::Unspecified> {
|
-> Result<Ed25519KeyPair, error::Unspecified> {
|
||||||
@ -265,3 +306,16 @@ const SIGNATURE_LEN: usize = ELEM_LEN + SCALAR_LEN;
|
|||||||
|
|
||||||
type Seed = [u8; SEED_LEN];
|
type Seed = [u8; SEED_LEN];
|
||||||
const SEED_LEN: usize = 32;
|
const SEED_LEN: usize = 32;
|
||||||
|
|
||||||
|
const PKCS8_TEMPLATE: &[u8] = include_bytes!("ed25519_pkcs8_v2_template.der");
|
||||||
|
const PKCS8_SEED_INDEX: usize = 0x0e;
|
||||||
|
const PKCS8_PUBLIC_KEY_INDEX: usize = 0x33;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn ed25519_alg_id() -> &'static [u8] { &PKCS8_TEMPLATE[7..12] }
|
||||||
|
|
||||||
|
/// The length of a Ed25519 PKCs#8 (v2) private key generated by
|
||||||
|
/// `Ed25519KeyPair::generate_pkcs8()`. Ed25519 PKCS#8 files generated by other
|
||||||
|
/// software may have different lengths, and `Ed25519KeyPair::generate_pkcs8()`
|
||||||
|
/// may generate files of a different length in the future.
|
||||||
|
pub const ED25519_PKCS8_V2_LEN: usize = 0x53;
|
||||||
|
BIN
src/ec/curve25519/ed25519_pkcs8_v2_template.der
Normal file
BIN
src/ec/curve25519/ed25519_pkcs8_v2_template.der
Normal file
Binary file not shown.
@ -153,7 +153,6 @@ mod init;
|
|||||||
mod limb;
|
mod limb;
|
||||||
pub mod pbkdf2;
|
pub mod pbkdf2;
|
||||||
|
|
||||||
#[cfg(feature = "rsa_signing")]
|
|
||||||
mod pkcs8;
|
mod pkcs8;
|
||||||
|
|
||||||
mod poly1305;
|
mod poly1305;
|
||||||
|
52
src/pkcs8.rs
52
src/pkcs8.rs
@ -12,29 +12,45 @@
|
|||||||
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
//! PKCS#8 is specified in [RFC 5958].
|
||||||
|
//!
|
||||||
|
//! [RFC 5958]: https://tools.ietf.org/html/rfc5958.
|
||||||
|
|
||||||
use {der, error};
|
use {der, error};
|
||||||
use untrusted;
|
use untrusted;
|
||||||
|
|
||||||
/// Parses an unencrypted PKCS#8 privatg key, verifies that it is the right type
|
pub enum Version {
|
||||||
/// of key, and returns the key value. `alg_id` must be the encoded value (not
|
#[cfg(feature = "rsa_signing")] V1Only,
|
||||||
/// including the outermost `SEQUENCE` tag and length) of the
|
V1OrV2,
|
||||||
/// `AlgorithmIdentifier` that identifies the key type. The result will be an
|
V2Only,
|
||||||
/// encoded `RSAPrivateKey` or `ECPrivateKey` or similar.
|
}
|
||||||
|
|
||||||
|
/// Parses an unencrypted PKCS#8 private key, verifies that it is the right type
|
||||||
|
/// of key, and returns the key value.
|
||||||
///
|
///
|
||||||
/// PKCS#8 is specified in [RFC 5958]. Only v1 keys are supported, as none of
|
/// `alg_id` must be the encoded value (not including the outermost `SEQUENCE`
|
||||||
/// the algorithms we support require v2 support.
|
/// tag and length) of the `AlgorithmIdentifier` that identifies the key type.
|
||||||
|
/// The result will be an encoded `RSAPrivateKey` or `ECPrivateKey` or similar.
|
||||||
|
///
|
||||||
|
/// PKCS#8 is specified in [RFC 5958].
|
||||||
///
|
///
|
||||||
/// [RFC 5958]: https://tools.ietf.org/html/rfc5958.
|
/// [RFC 5958]: https://tools.ietf.org/html/rfc5958.
|
||||||
pub fn unwrap_key<'a>(input: untrusted::Input<'a>, alg_id: &[u8])
|
pub fn unwrap_key<'a>(version: Version, input: untrusted::Input<'a>,
|
||||||
-> Result<untrusted::Input<'a>, error::Unspecified> {
|
alg_id: &[u8])
|
||||||
|
-> Result<(untrusted::Input<'a>, Option<untrusted::Input<'a>>),
|
||||||
|
error::Unspecified> {
|
||||||
input.read_all(error::Unspecified, |input| {
|
input.read_all(error::Unspecified, |input| {
|
||||||
der::nested(input, der::Tag::Sequence, error::Unspecified, |input| {
|
der::nested(input, der::Tag::Sequence, error::Unspecified, |input| {
|
||||||
// Currently we only support algorithms that should only be encoded
|
// Currently we only support algorithms that should only be encoded
|
||||||
// in v1 form, so reject v2 and any later form.
|
// in v1 form, so reject v2 and any later form.
|
||||||
let version = try!(der::small_nonnegative_integer(input));
|
let require_public_key =
|
||||||
if version != 0 {
|
match (try!(der::small_nonnegative_integer(input)), version) {
|
||||||
return Err(error::Unspecified);
|
#[cfg(feature = "rsa_signing")] (0, Version::V1Only) => false,
|
||||||
}
|
(0, Version::V1OrV2) => false,
|
||||||
|
(1, Version::V1OrV2) |
|
||||||
|
(1, Version::V2Only) => true,
|
||||||
|
_ => { return Err(error::Unspecified); }
|
||||||
|
};
|
||||||
|
|
||||||
let actual_alg_id =
|
let actual_alg_id =
|
||||||
try!(der::expect_tag_and_get_value(input, der::Tag::Sequence));
|
try!(der::expect_tag_and_get_value(input, der::Tag::Sequence));
|
||||||
@ -51,7 +67,15 @@ pub fn unwrap_key<'a>(input: untrusted::Input<'a>, alg_id: &[u8])
|
|||||||
der::Tag::ContextSpecificConstructed0));
|
der::Tag::ContextSpecificConstructed0));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(private_key)
|
let public_key = if require_public_key {
|
||||||
|
Some(try!(der::nested(
|
||||||
|
input, der::Tag::ContextSpecificConstructed1,
|
||||||
|
error::Unspecified, der::bit_string_with_no_unused_bits)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((private_key, public_key))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,8 @@ impl RSAKeyPair {
|
|||||||
-> Result<RSAKeyPair, error::Unspecified> {
|
-> Result<RSAKeyPair, error::Unspecified> {
|
||||||
const RSA_ENCRYPTION: &'static [u8] =
|
const RSA_ENCRYPTION: &'static [u8] =
|
||||||
include_bytes!("../data/alg-rsa-encryption.der");
|
include_bytes!("../data/alg-rsa-encryption.der");
|
||||||
let der = try!(pkcs8::unwrap_key(input, &RSA_ENCRYPTION));
|
let (der, _) = try!(pkcs8::unwrap_key(pkcs8::Version::V1Only, input,
|
||||||
|
&RSA_ENCRYPTION));
|
||||||
Self::from_der(der)
|
Self::from_der(der)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,30 +138,25 @@
|
|||||||
//! use ring::{rand, signature};
|
//! use ring::{rand, signature};
|
||||||
//!
|
//!
|
||||||
//! # fn sign_and_verify_ed25519() -> Result<(), ring::error::Unspecified> {
|
//! # fn sign_and_verify_ed25519() -> Result<(), ring::error::Unspecified> {
|
||||||
//! // Generate a key pair.
|
//! // Generate a key pair in PKCS#8 (v2) format.
|
||||||
//! let rng = rand::SystemRandom::new();
|
//! let rng = rand::SystemRandom::new();
|
||||||
//! let (generated, generated_bytes) =
|
//! let pkcs8_bytes = try!(signature::Ed25519KeyPair::generate_pkcs8(&rng));
|
||||||
//! try!(signature::Ed25519KeyPair::generate_serializable(&rng));
|
|
||||||
//!
|
//!
|
||||||
//! // Normally after generating the key pair, the application would extract
|
//! // Normally the application would store the PKCS#8 file persistently. Later
|
||||||
//! // the private and public components and store them persistently for future
|
//! // it would read the PKCS#8 file from persistent storage to use it.
|
||||||
//! // use.
|
|
||||||
//!
|
//!
|
||||||
//! // Normally the application would later deserialize the private and public
|
//! let key_pair =
|
||||||
//! // key from storage and then create an `Ed25519KeyPair` from the
|
//! try!(signature::Ed25519KeyPair::from_pkcs8(
|
||||||
//! // deserialized bytes.
|
//! untrusted::Input::from(&pkcs8_bytes)));
|
||||||
//! let key_pair = try!(signature::Ed25519KeyPair::from_seed_and_public_key(
|
|
||||||
//! untrusted::Input::from(&generated_bytes.private_key),
|
|
||||||
//! untrusted::Input::from(&generated_bytes.public_key)));
|
|
||||||
//!
|
//!
|
||||||
//! // Sign the message "hello, world".
|
//! // Sign the message "hello, world".
|
||||||
//! const MESSAGE: &'static [u8] = b"hello, world";
|
//! const MESSAGE: &'static [u8] = b"hello, world";
|
||||||
//! let sig = key_pair.sign(MESSAGE);
|
//! let sig = key_pair.sign(MESSAGE);
|
||||||
//!
|
//!
|
||||||
//! // Normally an application would extract the bytes of the signature and send
|
//! // Normally an application would extract the bytes of the signature and
|
||||||
//! // them in a protocol message to the peer(s). Here we just use the public
|
//! // send them in a protocol message to the peer(s). Here we just get the
|
||||||
//! // key from the private key we just generated.
|
//! // public key key directly from the key pair.
|
||||||
//! let peer_public_key_bytes = &generated_bytes.public_key;
|
//! let peer_public_key_bytes = key_pair.public_key_bytes();
|
||||||
//! let sig_bytes = sig.as_ref();
|
//! let sig_bytes = sig.as_ref();
|
||||||
//!
|
//!
|
||||||
//! // Verify the signature of the message using the public key. Normally the
|
//! // Verify the signature of the message using the public key. Normally the
|
||||||
@ -278,7 +273,7 @@ pub use ec::curve25519::ed25519::{
|
|||||||
ED25519,
|
ED25519,
|
||||||
|
|
||||||
Ed25519KeyPair,
|
Ed25519KeyPair,
|
||||||
Ed25519KeyPairBytes
|
ED25519_PKCS8_V2_LEN,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(all(feature = "rsa_signing", feature = "use_heap"))]
|
#[cfg(all(feature = "rsa_signing", feature = "use_heap"))]
|
||||||
|
1
tests/ed25519_test_private_key.bin
Normal file
1
tests/ed25519_test_private_key.bin
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>a±<EFBFBD>ïýZ`º„Jô’ì,ÄDIÅi{2ip;¬®`
|
2
tests/ed25519_test_public_key.bin
Normal file
2
tests/ed25519_test_public_key.bin
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
×Z<EFBFBD>‚±
|
||||||
|
·ŐKţÓÉd:áróÚ¦#%Żh÷Q
|
@ -15,7 +15,7 @@
|
|||||||
extern crate ring;
|
extern crate ring;
|
||||||
extern crate untrusted;
|
extern crate untrusted;
|
||||||
|
|
||||||
use ring::{rand, signature, test};
|
use ring::{signature, test};
|
||||||
use signature::Ed25519KeyPair;
|
use signature::Ed25519KeyPair;
|
||||||
|
|
||||||
/// Test vectors from BoringSSL.
|
/// Test vectors from BoringSSL.
|
||||||
@ -23,51 +23,67 @@ use signature::Ed25519KeyPair;
|
|||||||
fn test_signature_ed25519() {
|
fn test_signature_ed25519() {
|
||||||
test::from_file("tests/ed25519_tests.txt", |section, test_case| {
|
test::from_file("tests/ed25519_tests.txt", |section, test_case| {
|
||||||
assert_eq!(section, "");
|
assert_eq!(section, "");
|
||||||
let private_key = test_case.consume_bytes("PRIV");
|
let seed = test_case.consume_bytes("SEED");
|
||||||
assert_eq!(64, private_key.len());
|
assert_eq!(32, seed.len());
|
||||||
|
let seed = untrusted::Input::from(&seed);
|
||||||
|
|
||||||
let public_key = test_case.consume_bytes("PUB");
|
let public_key = test_case.consume_bytes("PUB");
|
||||||
assert_eq!(32, public_key.len());
|
assert_eq!(32, public_key.len());
|
||||||
|
let public_key = untrusted::Input::from(&public_key);
|
||||||
|
|
||||||
let msg = test_case.consume_bytes("MESSAGE");
|
let msg = test_case.consume_bytes("MESSAGE");
|
||||||
|
|
||||||
let expected_sig = test_case.consume_bytes("SIG");
|
let expected_sig = test_case.consume_bytes("SIG");
|
||||||
|
|
||||||
let key_pair =
|
{
|
||||||
Ed25519KeyPair::from_seed_and_public_key(
|
let key_pair = Ed25519KeyPair::from_seed_and_public_key(
|
||||||
untrusted::Input::from(&private_key[..32]),
|
seed, public_key).unwrap();
|
||||||
untrusted::Input::from(&public_key)).unwrap();
|
let actual_sig = key_pair.sign(&msg);
|
||||||
|
assert_eq!(&expected_sig[..], actual_sig.as_ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test PKCS#8 generation, parsing, and private-to-public calculations.
|
||||||
|
let rng = test::rand::FixedSliceRandom {
|
||||||
|
bytes: seed.as_slice_less_safe()
|
||||||
|
};
|
||||||
|
let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
|
||||||
|
let key_pair = Ed25519KeyPair::from_pkcs8(
|
||||||
|
untrusted::Input::from(&pkcs8)).unwrap();
|
||||||
|
assert_eq!(public_key, key_pair.public_key_bytes());
|
||||||
|
|
||||||
|
// Test Signature generation.
|
||||||
let actual_sig = key_pair.sign(&msg);
|
let actual_sig = key_pair.sign(&msg);
|
||||||
assert_eq!(&expected_sig[..], actual_sig.as_ref());
|
assert_eq!(&expected_sig[..], actual_sig.as_ref());
|
||||||
|
|
||||||
let public_key = untrusted::Input::from(&public_key);
|
// Test Signature verification.
|
||||||
let msg = untrusted::Input::from(&msg);
|
assert!(signature::verify(
|
||||||
let expected_sig = untrusted::Input::from(&expected_sig);
|
&signature::ED25519, public_key, untrusted::Input::from(&msg),
|
||||||
|
untrusted::Input::from(&expected_sig)).is_ok());
|
||||||
assert!(signature::verify(&signature::ED25519, public_key, msg,
|
|
||||||
expected_sig).is_ok());
|
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ed25519_from_seed_and_public_key_misuse() {
|
fn test_ed25519_from_seed_and_public_key_misuse() {
|
||||||
let rng = rand::SystemRandom::new();
|
const PRIVATE_KEY: &[u8] = include_bytes!("ed25519_test_private_key.bin");
|
||||||
let (_, bytes) = Ed25519KeyPair::generate_serializable(&rng).unwrap();
|
const PUBLIC_KEY: &[u8] = include_bytes!("ed25519_test_public_key.bin");
|
||||||
|
|
||||||
assert!(Ed25519KeyPair::from_seed_and_public_key(
|
assert!(Ed25519KeyPair::from_seed_and_public_key(
|
||||||
untrusted::Input::from(&bytes.private_key),
|
untrusted::Input::from(PRIVATE_KEY),
|
||||||
untrusted::Input::from(&bytes.public_key)).is_ok());
|
untrusted::Input::from(PUBLIC_KEY)).is_ok());
|
||||||
|
|
||||||
// Truncated private key.
|
// Truncated private key.
|
||||||
assert!(Ed25519KeyPair::from_seed_and_public_key(
|
assert!(Ed25519KeyPair::from_seed_and_public_key(
|
||||||
untrusted::Input::from(&bytes.private_key[..31]),
|
untrusted::Input::from(&PRIVATE_KEY[..31]),
|
||||||
untrusted::Input::from(&bytes.public_key)).is_err());
|
untrusted::Input::from(PUBLIC_KEY)).is_err());
|
||||||
|
|
||||||
// Truncated public key.
|
// Truncated public key.
|
||||||
assert!(Ed25519KeyPair::from_seed_and_public_key(
|
assert!(Ed25519KeyPair::from_seed_and_public_key(
|
||||||
untrusted::Input::from(&bytes.private_key),
|
untrusted::Input::from(PRIVATE_KEY),
|
||||||
untrusted::Input::from(&bytes.public_key[..31])).is_err());
|
untrusted::Input::from(&PUBLIC_KEY[..31])).is_err());
|
||||||
|
|
||||||
// Swapped public and private key.
|
// Swapped public and private key.
|
||||||
assert!(Ed25519KeyPair::from_seed_and_public_key(
|
assert!(Ed25519KeyPair::from_seed_and_public_key(
|
||||||
untrusted::Input::from(&bytes.public_key),
|
untrusted::Input::from(PUBLIC_KEY),
|
||||||
untrusted::Input::from(&bytes.private_key)).is_err());
|
untrusted::Input::from(PRIVATE_KEY)).is_err());
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user