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
|
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ZeroCopyBuf;
use elliptic_curve::pkcs8::PrivateKeyInfo;
use rand::rngs::OsRng;
use rand::RngCore;
use ring::signature::Ed25519KeyPair;
use ring::signature::KeyPair;
use spki::der::Decode;
use spki::der::Encode;
#[op(fast)]
pub fn op_generate_ed25519_keypair(pkey: &mut [u8], pubkey: &mut [u8]) -> bool {
let mut rng = OsRng;
rng.fill_bytes(pkey);
let pair = match Ed25519KeyPair::from_seed_unchecked(pkey) {
Ok(p) => p,
Err(_) => return false,
};
pubkey.copy_from_slice(pair.public_key().as_ref());
true
}
#[op(fast)]
pub fn op_sign_ed25519(key: &[u8], data: &[u8], signature: &mut [u8]) -> bool {
let pair = match Ed25519KeyPair::from_seed_unchecked(key) {
Ok(p) => p,
Err(_) => return false,
};
signature.copy_from_slice(pair.sign(data).as_ref());
true
}
#[op(fast)]
pub fn op_verify_ed25519(pubkey: &[u8], data: &[u8], signature: &[u8]) -> bool {
ring::signature::UnparsedPublicKey::new(&ring::signature::ED25519, pubkey)
.verify(data, signature)
.is_ok()
}
// id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 }
pub const ED25519_OID: const_oid::ObjectIdentifier =
const_oid::ObjectIdentifier::new_unwrap("1.3.101.112");
#[op(fast)]
pub fn op_import_spki_ed25519(key_data: &[u8], out: &mut [u8]) -> bool {
// 2-3.
let pk_info = match spki::SubjectPublicKeyInfo::from_der(key_data) {
Ok(pk_info) => pk_info,
Err(_) => return false,
};
// 4.
let alg = pk_info.algorithm.oid;
if alg != ED25519_OID {
return false;
}
// 5.
if pk_info.algorithm.parameters.is_some() {
return false;
}
out.copy_from_slice(pk_info.subject_public_key);
true
}
#[op(fast)]
pub fn op_import_pkcs8_ed25519(key_data: &[u8], out: &mut [u8]) -> bool {
// 2-3.
let pk_info = match PrivateKeyInfo::from_der(key_data) {
Ok(pk_info) => pk_info,
Err(_) => return false,
};
// 4.
let alg = pk_info.algorithm.oid;
if alg != ED25519_OID {
return false;
}
// 5.
if pk_info.algorithm.parameters.is_some() {
return false;
}
// 6.
// CurvePrivateKey ::= OCTET STRING
if pk_info.private_key.len() != 32 {
return false;
}
out.copy_from_slice(pk_info.private_key);
true
}
#[op]
pub fn op_export_spki_ed25519(pubkey: &[u8]) -> Result<ZeroCopyBuf, AnyError> {
let key_info = spki::SubjectPublicKeyInfo {
algorithm: spki::AlgorithmIdentifier {
// id-Ed25519
oid: ED25519_OID,
parameters: None,
},
subject_public_key: pubkey,
};
Ok(key_info.to_vec()?.into())
}
#[op]
pub fn op_export_pkcs8_ed25519(pkey: &[u8]) -> Result<ZeroCopyBuf, AnyError> {
let pk_info = rsa::pkcs8::PrivateKeyInfo {
public_key: None,
algorithm: rsa::pkcs8::AlgorithmIdentifier {
// id-Ed25519
oid: ED25519_OID,
parameters: None,
},
private_key: pkey, // OCTET STRING
};
Ok(pk_info.to_vec()?.into())
}
// 'x' from Section 2 of RFC 8037
// https://www.rfc-editor.org/rfc/rfc8037#section-2
#[op]
pub fn op_jwk_x_ed25519(pkey: &[u8]) -> Result<String, AnyError> {
let pair = Ed25519KeyPair::from_seed_unchecked(pkey)?;
Ok(base64::encode_config(
pair.public_key().as_ref(),
base64::URL_SAFE_NO_PAD,
))
}
|