-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathCryptoExample.re
More file actions
114 lines (106 loc) · 2.96 KB
/
CryptoExample.re
File metadata and controls
114 lines (106 loc) · 2.96 KB
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
open WebapiExtra.Dom;
let algorithm = "RSASSA-PKCS1-v1_5";
let hash = "SHA-256";
let arrayBufferToBase64 = buffer =>
Js.Typed_array.(
Uint8Array.fromBuffer(buffer)
|> Uint8Array.reduce(
(. binary, b) => binary ++ Js.String.fromCharCode(b),
"",
)
|> Webapi.Base64.btoa
);
let stringToArrayBuffer = str =>
TextEncoder.create()
->TextEncoder.encode(str)
->Js.Typed_array.Uint8Array.buffer;
exception JWKMissingKeys(string);
exception InternalError(string);
/* https://tools.ietf.org/html/rfc7638 */
let fingerprintForRSAJWK = (jwk: jsonWebKey) =>
switch (jwk##e, jwk##kty, jwk##n) {
| (Some(e), Some(kty), Some(n)) =>
switch (Js.Json.stringifyAny({"e": e, "kty": kty, "n": n})) {
| Some(str) =>
str
|> stringToArrayBuffer
|> crypto->Crypto.subtle->SubtleCrypto.digest(hash)
|> Js.Promise.then_(digestArrayBuffer =>
Js.Promise.resolve(arrayBufferToBase64(digestArrayBuffer))
)
| None => Js.Promise.reject @@ InternalError("Stringify failed.")
}
| _ =>
Js.Promise.reject @@
JWKMissingKeys("JWK must contain all of the following keys: e, kty, n.")
};
type state = {
keyPair1: cryptoKeyPair,
keyPair1Fingerprint: string,
keyPair2: cryptoKeyPair,
};
let run = () => {
let subtle = crypto->Crypto.subtle;
let strToSign = "Pleeeee";
let then_ = Js.Promise.then_;
let thenl = cb =>
Js.Promise.then_(v => {
Js.log(v);
cb(v);
});
subtle
->SubtleCrypto.generateKeyPair(
RsaHashedKeyGenParams.make(
~name=algorithm,
~modulusLength=2048,
~publicExponent=Js.Typed_array.Uint8Array.make([|0x01, 0x00, 0x01|]),
~hash=HashAlgorithmIdentifier.make(~name=hash),
),
false,
[|`Sign, `Verify|],
)
|> then_(keyPair =>
subtle
->SubtleCrypto.sign(
algorithm,
keyPair->CryptoKeyPair.privateKey,
stringToArrayBuffer(strToSign),
)
|> then_(signature =>
subtle
->SubtleCrypto.verify(
algorithm,
keyPair->CryptoKeyPair.publicKey,
signature,
stringToArrayBuffer("hasdf"),
)
)
|> thenl(_ =>
fingerprintForRSAJWK(
JsonWebKey.create(~e="e", ~n="n", ~kty="kty", ()),
)
)
|> thenl(_ =>
subtle->SubtleCrypto.exportKey(keyPair->CryptoKeyPair.publicKey)
)
)
|> thenl(jwk =>
fingerprintForRSAJWK(jwk)
|> thenl(_ =>
subtle
->SubtleCrypto.importKey(
jwk,
RsaHashedImportParams.make(
~name=algorithm,
~hash=HashAlgorithmIdentifier.make(~name=hash),
),
true,
[|`Verify|],
)
)
)
|> thenl(subtle->SubtleCrypto.exportKey)
|> thenl(fingerprintForRSAJWK)
|> thenl(Js.Promise.resolve);
};
run();