1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
use {
crate::BlackHole, ring::signature::ED25519_PKCS8_V2_LEN, std::fmt::Display, std::ops::Deref,
untrusted::Input,
};
pub use ring::signature::{
VerificationAlgorithm,
ECDSA_P256_SHA384_ASN1, // not recommended. verification of asn.1 der-encoded ecdsa signatures using the p-256 curve and sha-384.
ECDSA_P384_SHA256_ASN1, // not recommended. verification of asn.1 der-encoded ecdsa signatures using the p-384 curve and sha-256.
ECDSA_P384_SHA384_ASN1, // verification of asn.1 der-encoded ecdsa signatures using the p-384 curve and sha-384.
ECDSA_P384_SHA384_FIXED, // verification of fixed-length (pkcs#11 style) ecdsa signatures using the p-384 curve and sha-384.
ED25519, // verification of ed25519 signatures.
RSA_PKCS1_2048_8192_SHA1, // verification of signatures using rsa keys of 2048-8192 bits, pkcs#1.5 padding, and sha-1.
RSA_PKCS1_2048_8192_SHA256, // verification of signatures using rsa keys of 2048-8192 bits, pkcs#1.5 padding, and sha-256.
RSA_PKCS1_2048_8192_SHA384, // verification of signatures using rsa keys of 2048-8192 bits, pkcs#1.5 padding, and sha-384.
RSA_PKCS1_2048_8192_SHA512, // verification of signatures using rsa keys of 2048-8192 bits, pkcs#1.5 padding, and sha-512.
RSA_PKCS1_3072_8192_SHA384, // verification of signatures using rsa keys of 3072-8192 bits, pkcs#1.5 padding, and sha-384.
RSA_PKCS1_SHA256, // pkcs#1 1.5 padding using sha-256 for rsa signatures.
RSA_PKCS1_SHA384, // pkcs#1 1.5 padding using sha-384 for rsa signatures.
RSA_PKCS1_SHA512, // pkcs#1 1.5 padding using sha-512 for rsa signatures.
RSA_PSS_2048_8192_SHA256, // verification of signatures using rsa keys of 2048-8192 bits, pss padding, and sha-256.
RSA_PSS_2048_8192_SHA384, // verification of signatures using rsa keys of 2048-8192 bits, pss padding, and sha-384.
RSA_PSS_2048_8192_SHA512, // verification of signatures using rsa keys of 2048-8192 bits, pss padding, and sha-512.
RSA_PSS_SHA256, // rsa pss padding using sha-256 for rsa signatures.
RSA_PSS_SHA384, // rsa pss padding using sha-384 for rsa signatures.
RSA_PSS_SHA512, // rsa pss padding using sha-512 for rsa signatures.
};
pub struct Signature {
underlying: ring::signature::Signature,
}
impl AsRef<[u8]> for Signature {
fn as_ref(&self) -> &[u8] {
self.underlying.as_ref()
}
}
impl Deref for Signature {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.underlying.as_ref()
}
}
pub struct Ed25519KeyPair {
underlying: ring::signature::Ed25519KeyPair,
}
impl Ed25519KeyPair {
/// generates a new key pair and returns the key pair serialized as a pkcs#8 document.
///
/// 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.
///
/// [rfc 5958 section 2]: https://tools.ietf.org/html/rfc5958#section-2
pub fn generate_pkcs8(
random: &ring::rand::SecureRandom,
) -> Result<[u8; ED25519_PKCS8_V2_LEN], BlackHole> {
ring::signature::Ed25519KeyPair::generate_pkcs8(random).map_err(From::from)
}
/// constructs an ed25519 key pair by parsing an unencrypted 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(key: &[u8]) -> Result<Ed25519KeyPair, BlackHole> {
let input = Input::from(key);
let underlying = ring::signature::Ed25519KeyPair::from_pkcs8(input)?;
Ok(Ed25519KeyPair { underlying })
}
/// constructs an ed25519 key pair by parsing an unencrypted 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: &[u8]) -> Result<Ed25519KeyPair, BlackHole> {
let input = Input::from(input);
let underlying = ring::signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(input)?;
Ok(Ed25519KeyPair { underlying })
}
/// constructs an ed25519 key pair from the private key seed `seed` and its public key `public_key`.
///
/// it is recommended to use `ed25519keypair::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: &[u8],
public_key: &[u8],
) -> Result<Ed25519KeyPair, BlackHole> {
let seed = Input::from(seed);
let public_key = Input::from(public_key);
let underlying =
ring::signature::Ed25519KeyPair::from_seed_and_public_key(seed, public_key)?;
Ok(Ed25519KeyPair { underlying })
}
/// constructs a ed25519 key pair from the private key seed `seed`.
///
/// it is recommended to use `ed25519keypair::from_pkcs8()` instead. when that is not practical, it is recommended
/// to use `ed25519keypair::from_seed_and_public_key()` instead.
///
/// since the public key is not given, the public key will be computed from the private key. it is not possible to
/// detect misuse or corruption of the private key since the public key isn't given as input.
pub fn from_seed_unchecked(seed: &[u8]) -> Result<Ed25519KeyPair, BlackHole> {
let seed = Input::from(seed);
let underlying = ring::signature::Ed25519KeyPair::from_seed_unchecked(seed)?;
Ok(Ed25519KeyPair { underlying })
}
/// returns a reference to the little-endian encoded bytes for this pair's public key.
pub fn public_key_bytes(&self) -> &[u8] {
self.underlying.public_key_bytes()
}
/// signs `message` using this pair's private key, and returns its signature.
pub fn sign(&self, message: &[u8]) -> Signature {
Signature {
underlying: self.underlying.sign(message),
}
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct SignatureError;
impl Display for SignatureError {
fn fmt(&self, _: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
Ok(())
}
}
pub fn validate_signature(
algorithm: &VerificationAlgorithm,
public_key: &[u8],
message: &[u8],
signature: &[u8],
) -> Result<(), SignatureError> {
ring::signature::verify(
algorithm,
Input::from(public_key),
Input::from(message),
Input::from(signature),
)
.map_err(|_| SignatureError)
}