@pezkuwi/wasm-crypto 7.5.13 → 7.5.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/Cargo.toml +50 -0
  2. package/Xargo.toml +2 -0
  3. package/build/README.md +29 -0
  4. package/build/bundle-pezkuwi-wasm-crypto.js +2092 -0
  5. package/build/bundle.d.ts +40 -0
  6. package/build/bundle.js +505 -0
  7. package/build/cjs/bundle.d.ts +40 -0
  8. package/build/cjs/bundle.js +544 -0
  9. package/{index.d.ts → build/cjs/index.d.ts} +0 -1
  10. package/build/cjs/index.js +4 -0
  11. package/build/cjs/init.js +21 -0
  12. package/build/cjs/initNone.js +20 -0
  13. package/build/cjs/initOnlyAsm.js +20 -0
  14. package/build/cjs/initOnlyWasm.js +20 -0
  15. package/build/cjs/initWasmAsm.js +20 -0
  16. package/build/cjs/packageInfo.js +4 -0
  17. package/build/index.d.ts +1 -0
  18. package/build/index.js +1 -0
  19. package/build/init.d.ts +16 -0
  20. package/build/init.js +17 -0
  21. package/build/initNone.d.ts +10 -0
  22. package/build/initNone.js +17 -0
  23. package/build/initOnlyAsm.d.ts +10 -0
  24. package/build/initOnlyAsm.js +17 -0
  25. package/build/initOnlyWasm.d.ts +10 -0
  26. package/build/initOnlyWasm.js +17 -0
  27. package/build/initWasmAsm.d.ts +10 -0
  28. package/build/initWasmAsm.js +17 -0
  29. package/build/package.json +208 -0
  30. package/build/packageDetect.d.ts +1 -0
  31. package/build/packageDetect.js +8 -0
  32. package/build/packageInfo.d.ts +6 -0
  33. package/build/packageInfo.js +1 -0
  34. package/build-deno/README.md +25 -0
  35. package/build-deno/bundle.ts +597 -0
  36. package/build-deno/index.ts +2 -0
  37. package/build-deno/init.ts +23 -0
  38. package/build-deno/initNone.ts +21 -0
  39. package/build-deno/initOnlyAsm.ts +21 -0
  40. package/build-deno/initOnlyWasm.ts +21 -0
  41. package/build-deno/initWasmAsm.ts +21 -0
  42. package/build-deno/mod.ts +2 -0
  43. package/build-deno/packageDetect.ts +12 -0
  44. package/build-deno/packageInfo.ts +3 -0
  45. package/build-deno/rs/.editorconfig +10 -0
  46. package/build-tsc/bundle.d.ts +40 -0
  47. package/{cjs → build-tsc}/index.d.ts +0 -1
  48. package/build-tsc-cjs/bundle.js +544 -0
  49. package/{cjs → build-tsc-cjs}/index.js +0 -1
  50. package/build-tsc-cjs/packageDetect.js +10 -0
  51. package/{cjs → build-tsc-cjs}/packageInfo.js +1 -1
  52. package/build-tsc-esm/bundle.js +505 -0
  53. package/{index.js → build-tsc-esm/index.js} +0 -1
  54. package/{packageInfo.js → build-tsc-esm/packageInfo.js} +1 -1
  55. package/package.json +89 -87
  56. package/src/bundle.ts +613 -0
  57. package/src/index.ts +5 -0
  58. package/src/init.ts +25 -0
  59. package/src/initNone.ts +23 -0
  60. package/src/initOnlyAsm.ts +23 -0
  61. package/src/initOnlyWasm.ts +23 -0
  62. package/src/initWasmAsm.ts +23 -0
  63. package/src/lib.rs +24 -0
  64. package/src/mod.ts +4 -0
  65. package/src/packageDetect.ts +16 -0
  66. package/src/packageInfo.ts +6 -0
  67. package/src/rs/.editorconfig +10 -0
  68. package/src/rs/bip39.rs +139 -0
  69. package/src/rs/ed25519.rs +142 -0
  70. package/src/rs/hashing.rs +322 -0
  71. package/src/rs/secp256k1.rs +150 -0
  72. package/src/rs/sr25519.rs +331 -0
  73. package/src/rs/vrf.rs +144 -0
  74. package/test/all/bip39.js +86 -0
  75. package/test/all/ed25519.js +84 -0
  76. package/test/all/hashing.js +138 -0
  77. package/test/all/index.js +126 -0
  78. package/test/all/secp256k1.js +105 -0
  79. package/test/all/sr25519.js +211 -0
  80. package/test/all/vrf.js +74 -0
  81. package/test/asm.js +10 -0
  82. package/test/deno.ts +38 -0
  83. package/test/jest.spec.ts +25 -0
  84. package/test/loader-build.js +39 -0
  85. package/test/wasm.js +8 -0
  86. package/tsconfig.build.json +19 -0
  87. package/tsconfig.build.tsbuildinfo +1 -0
  88. package/tsconfig.spec.json +16 -0
  89. package/tsconfig.spec.tsbuildinfo +1 -0
  90. package/bundle-pezkuwi-wasm-crypto.js +0 -825
  91. package/bundle.d.ts +0 -37
  92. package/bundle.js +0 -165
  93. package/cjs/bundle.d.ts +0 -37
  94. package/cjs/bundle.js +0 -171
  95. /package/{LICENSE → build/LICENSE} +0 -0
  96. /package/{init.d.ts → build/cjs/init.d.ts} +0 -0
  97. /package/{initNone.d.ts → build/cjs/initNone.d.ts} +0 -0
  98. /package/{initOnlyAsm.d.ts → build/cjs/initOnlyAsm.d.ts} +0 -0
  99. /package/{initOnlyWasm.d.ts → build/cjs/initOnlyWasm.d.ts} +0 -0
  100. /package/{initWasmAsm.d.ts → build/cjs/initWasmAsm.d.ts} +0 -0
  101. /package/{cjs → build/cjs}/package.json +0 -0
  102. /package/{packageDetect.d.ts → build/cjs/packageDetect.d.ts} +0 -0
  103. /package/{cjs → build/cjs}/packageDetect.js +0 -0
  104. /package/{packageInfo.d.ts → build/cjs/packageInfo.d.ts} +0 -0
  105. /package/{cjs → build-tsc}/init.d.ts +0 -0
  106. /package/{cjs → build-tsc}/initNone.d.ts +0 -0
  107. /package/{cjs → build-tsc}/initOnlyAsm.d.ts +0 -0
  108. /package/{cjs → build-tsc}/initOnlyWasm.d.ts +0 -0
  109. /package/{cjs → build-tsc}/initWasmAsm.d.ts +0 -0
  110. /package/{cjs → build-tsc}/packageDetect.d.ts +0 -0
  111. /package/{cjs → build-tsc}/packageInfo.d.ts +0 -0
  112. /package/{cjs → build-tsc-cjs}/init.js +0 -0
  113. /package/{cjs → build-tsc-cjs}/initNone.js +0 -0
  114. /package/{cjs → build-tsc-cjs}/initOnlyAsm.js +0 -0
  115. /package/{cjs → build-tsc-cjs}/initOnlyWasm.js +0 -0
  116. /package/{cjs → build-tsc-cjs}/initWasmAsm.js +0 -0
  117. /package/{init.js → build-tsc-esm/init.js} +0 -0
  118. /package/{initNone.js → build-tsc-esm/initNone.js} +0 -0
  119. /package/{initOnlyAsm.js → build-tsc-esm/initOnlyAsm.js} +0 -0
  120. /package/{initOnlyWasm.js → build-tsc-esm/initOnlyWasm.js} +0 -0
  121. /package/{initWasmAsm.js → build-tsc-esm/initWasmAsm.js} +0 -0
  122. /package/{packageDetect.js → build-tsc-esm/packageDetect.js} +0 -0
@@ -0,0 +1,322 @@
1
+ // Copyright 2019-2025 @pezkuwi/wasm-crypto authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ use blake2_rfc::blake2b::blake2b;
5
+ use byteorder::{ByteOrder, LittleEndian};
6
+ use hmac::{Hmac, Mac};
7
+ use pbkdf2::pbkdf2;
8
+ use scrypt::{ScryptParams, scrypt};
9
+ use sha2::{Digest, Sha256, Sha512};
10
+ use tiny_keccak::{Hasher, Keccak};
11
+ use twox_hash::XxHash;
12
+ use wasm_bindgen::prelude::*;
13
+
14
+ /// blake2b hash for the specified input
15
+ ///
16
+ /// * data: Arbitrary data to be hashed
17
+ /// * key: Key to add to the hashing (normally empty)
18
+ /// * size: Size in bytes of the resulting output
19
+ ///
20
+ /// Returns a vector with the hash result
21
+ #[wasm_bindgen]
22
+ pub fn ext_blake2b(data: &[u8], key: &[u8], size: u32) -> Vec<u8> {
23
+ // we cast to usize here - due to the WASM, we'd rather have u32 inputs
24
+ blake2b(size as usize, key, data)
25
+ .as_bytes()
26
+ .to_vec()
27
+ }
28
+
29
+ /// hmac with sha256
30
+ #[wasm_bindgen]
31
+ pub fn ext_hmac_sha256(key: &[u8], data: &[u8]) -> Vec<u8> {
32
+ match Hmac::<Sha256>::new_varkey(key) {
33
+ Ok(mut m) => {
34
+ m.input(data);
35
+
36
+ m
37
+ .result()
38
+ .code()
39
+ .to_vec()
40
+ },
41
+ _ => panic!("Invalid key provided.")
42
+ }
43
+ }
44
+
45
+ /// hmac with sha512
46
+ #[wasm_bindgen]
47
+ pub fn ext_hmac_sha512(key: &[u8], data: &[u8]) -> Vec<u8> {
48
+ match Hmac::<Sha512>::new_varkey(key) {
49
+ Ok(mut m) => {
50
+ m.input(data);
51
+
52
+ m
53
+ .result()
54
+ .code()
55
+ .to_vec()
56
+ },
57
+ _ => panic!("Invalid key provided.")
58
+ }
59
+
60
+ }
61
+
62
+ /// Create a keccak256 hash for the specified input
63
+ ///
64
+ // * data: Arbitrary data to be hashed
65
+ ///
66
+ /// Returns the hash as a vector
67
+ #[wasm_bindgen]
68
+ pub fn ext_keccak256(data: &[u8]) -> Vec<u8> {
69
+ let mut keccak = Keccak::v256();
70
+ let mut res = [0u8; 32];
71
+
72
+ keccak.update(data);
73
+ keccak.finalize(&mut res);
74
+
75
+ res.to_vec()
76
+ }
77
+
78
+ /// Create a keccak512 hash for the specified input
79
+ ///
80
+ // * data: Arbitrary data to be hashed
81
+ ///
82
+ /// Returns the hash as a vector
83
+ #[wasm_bindgen]
84
+ pub fn ext_keccak512(data: &[u8]) -> Vec<u8> {
85
+ let mut keccak = Keccak::v512();
86
+ let mut res = [0u8; 64];
87
+
88
+ keccak.update(data);
89
+ keccak.finalize(&mut res);
90
+
91
+ res.to_vec()
92
+ }
93
+
94
+ /// pbkdf2 kdf from an input, salt for the number of specified rounds
95
+ ///
96
+ /// * data: Arbitrary data to be hashed
97
+ /// * salt: Salt for this hash
98
+ /// * rounds: The number of rounds to perform
99
+ ///
100
+ /// Returns a vector with the hashed result
101
+ #[wasm_bindgen]
102
+ pub fn ext_pbkdf2(data: &[u8], salt: &[u8], rounds: u32) -> Vec<u8> {
103
+ // As per RFC 2898 [https://datatracker.ietf.org/doc/html/rfc2898], the number of rounds must be greater than 0
104
+ if rounds == 0 {
105
+ panic!("PBKDF2 rounds must be greater than 0");
106
+ }
107
+
108
+ let mut res = [0u8; 64];
109
+
110
+ // we cast to usize here - due to the WASM, we'd rather have u32 inputs
111
+ pbkdf2::<Hmac::<Sha512>>(data, salt, rounds as usize, &mut res);
112
+
113
+ res.to_vec()
114
+ }
115
+
116
+ /// scrypt kdf from input, salt and config
117
+ ///
118
+ /// * password: Password to hash
119
+ /// * salt: Salt for this hash
120
+ /// * log2_n: log2(n)
121
+ /// * r: r
122
+ /// * p: p
123
+ ///
124
+ /// Returns vector with the hashed result
125
+ #[wasm_bindgen]
126
+ pub fn ext_scrypt(password: &[u8], salt: &[u8], log2_n: u8, r: u32, p: u32) -> Vec<u8> {
127
+ // As per RFC 7914 [https://datatracker.ietf.org/doc/html/rfc7914.html], the cost parameter N (2 ^ log2_n) must be larger than 1
128
+ if log2_n == 0 {
129
+ panic!("Scrypt cost parameter N must be larger than 1, log2_n must be at least 1");
130
+ }
131
+
132
+ match ScryptParams::new(log2_n, r, p) {
133
+ Ok(p) => {
134
+ let mut res = [0u8; 64];
135
+
136
+ match scrypt(password, salt, &p, &mut res) {
137
+ Ok(_) => res.to_vec(),
138
+ _ => panic!("Invalid scrypt hash.")
139
+ }
140
+ },
141
+ _ => panic!("Invalid scrypt params.")
142
+ }
143
+
144
+ }
145
+
146
+ /// sha256 hash for the specified input
147
+ ///
148
+ /// * data: Arbitrary data to be hashed
149
+ ///
150
+ /// Returns a vector with the hash result
151
+ #[wasm_bindgen]
152
+ pub fn ext_sha256(data: &[u8]) -> Vec<u8> {
153
+ let mut hasher = Sha256::new();
154
+
155
+ hasher.input(data);
156
+
157
+ hasher
158
+ .result()
159
+ .to_vec()
160
+ }
161
+
162
+ /// sha512 hash for the specified input
163
+ ///
164
+ /// * data: Arbitrary data to be hashed
165
+ ///
166
+ /// Returns a vector with the hash result
167
+ #[wasm_bindgen]
168
+ pub fn ext_sha512(data: &[u8]) -> Vec<u8> {
169
+ let mut hasher = Sha512::new();
170
+
171
+ hasher.input(data);
172
+
173
+ hasher
174
+ .result()
175
+ .to_vec()
176
+ }
177
+
178
+ /// twox hash for the specified input and rounds
179
+ ///
180
+ /// * data: Arbitrary data to be hashed
181
+ /// * rounds: Number of 8-byte rounds to add to the output
182
+ ///
183
+ /// Returns a vector with the hash result
184
+ #[wasm_bindgen]
185
+ pub fn ext_twox(data: &[u8], rounds: u32) -> Vec<u8> {
186
+ use ::std::hash::Hasher;
187
+ let mut res = vec![];
188
+ let mut buf = [0u8; 8];
189
+
190
+ for round in 0..rounds {
191
+ // we cast to u64 here - due to the WASM, we'd rather have u32 inputs
192
+ let mut hasher = XxHash::with_seed(round as u64);
193
+
194
+ hasher.write(data);
195
+ LittleEndian::write_u64(&mut buf, hasher.finish());
196
+ res.extend_from_slice(&buf);
197
+ }
198
+
199
+ res
200
+ }
201
+
202
+ #[cfg(test)]
203
+ pub mod tests {
204
+ use hex_literal::hex;
205
+ use super::*;
206
+
207
+ #[test]
208
+ fn can_blake2b() {
209
+ let data = b"abc";
210
+ let expected_32 = hex!("bddd813c634239723171ef3fee98579b94964e3bb1cb3e427262c8c068d52319");
211
+ let expected_64 = hex!("ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923");
212
+ let hash_32 = ext_blake2b(data, &[], 32);
213
+ let hash_64 = ext_blake2b(data, &[], 64);
214
+
215
+ assert_eq!(hash_32[..], expected_32[..]);
216
+ assert_eq!(hash_64[..], expected_64[..]);
217
+ }
218
+
219
+ #[test]
220
+ fn can_keccak256() {
221
+ let data = b"test value";
222
+ let expected = hex!("2d07364b5c231c56ce63d49430e085ea3033c750688ba532b24029124c26ca5e");
223
+ let hash = ext_keccak256(data);
224
+
225
+ assert_eq!(hash[..], expected[..]);
226
+ }
227
+
228
+ #[test]
229
+ fn can_hmac_sha256() {
230
+ let key = b"secret";
231
+ let data = b"some message";
232
+ let expected = hex!("f28a70b41263840e5c059a0a733336e0957efba87902aa8cca11441d4b0c96d7");
233
+ let hash = ext_hmac_sha256(key, data);
234
+
235
+ assert_eq!(hash[..], expected[..]);
236
+ }
237
+
238
+ #[test]
239
+ fn can_hmac_sha512() {
240
+ let key = b"secret";
241
+ let data = b"some message";
242
+ let expected = hex!("295832e97ed77be75a9fa98029497e4a722c4b9a2f21b39d34f1befa931a39ec520fd24711d6f5c03501384ea66b83066a01a82c57a0460f8cd1f471fcce5841");
243
+ let hash = ext_hmac_sha512(key, data);
244
+
245
+ assert_eq!(hash[..], expected[..]);
246
+ }
247
+
248
+ #[test]
249
+ fn can_keccak512() {
250
+ let data = b"test";
251
+ let expected = hex!("1e2e9fc2002b002d75198b7503210c05a1baac4560916a3c6d93bcce3a50d7f00fd395bf1647b9abb8d1afcc9c76c289b0c9383ba386a956da4b38934417789e");
252
+ let hash = ext_keccak512(data);
253
+
254
+ assert_eq!(hash[..], expected[..]);
255
+ }
256
+
257
+ #[test]
258
+ fn can_pbkdf2() {
259
+ let salt = b"this is a salt";
260
+ let data = b"hello world";
261
+ let expected = hex!("5fcbe04f05300a3ecc5c35d18ea0b78f3f6853d2ae5f3fca374f69a7d1f78b5def5c60dae1a568026c7492511e0c53521e8bb6e03a650e1263265fee92722270");
262
+ let hash = ext_pbkdf2(data, salt, 2048);
263
+
264
+ assert_eq!(hash[..], expected[..]);
265
+ }
266
+
267
+ #[test]
268
+ #[should_panic(expected = "PBKDF2 rounds must be greater than 0")]
269
+ fn pbkdf2_zero_rounds_panics() {
270
+ let salt = b"this is a salt";
271
+ let data = b"hello world";
272
+ ext_pbkdf2(data, salt, 0);
273
+ }
274
+
275
+ #[test]
276
+ fn can_scrypt() {
277
+ let password = b"password";
278
+ let salt = b"salt";
279
+ let expected = hex!("745731af4484f323968969eda289aeee005b5903ac561e64a5aca121797bf7734ef9fd58422e2e22183bcacba9ec87ba0c83b7a2e788f03ce0da06463433cda6");
280
+ let hash = ext_scrypt(password, salt, 14, 8, 1);
281
+
282
+ assert_eq!(hash[..], expected[..]);
283
+ }
284
+
285
+ #[test]
286
+ #[should_panic(expected = "Scrypt cost parameter N must be larger than 1, log2_n must be at least 1")]
287
+ fn scrypt_zero_log2_n_panics() {
288
+ let password = b"password";
289
+ let salt = b"salt";
290
+ ext_scrypt(password, salt, 0, 8, 1);
291
+ }
292
+
293
+ #[test]
294
+ fn can_sha256() {
295
+ let data = b"hello world";
296
+ let expected = hex!("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9");
297
+ let hash = ext_sha256(data);
298
+
299
+ assert_eq!(hash[..], expected[..]);
300
+ }
301
+
302
+ #[test]
303
+ fn can_sha512() {
304
+ let data = b"hello world";
305
+ let expected = hex!("309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f");
306
+ let hash = ext_sha512(data);
307
+
308
+ assert_eq!(hash[..], expected[..]);
309
+ }
310
+
311
+ #[test]
312
+ fn can_twox() {
313
+ let data = b"abc";
314
+ let expected_64 = hex!("990977adf52cbc44");
315
+ let expected_256 = hex!("990977adf52cbc440889329981caa9bef7da5770b2b8a05303b75d95360dd62b");
316
+ let hash_64 = ext_twox(data, 1);
317
+ let hash_256 = ext_twox(data, 4);
318
+
319
+ assert_eq!(hash_64[..], expected_64[..]);
320
+ assert_eq!(hash_256[..], expected_256[..]);
321
+ }
322
+ }
@@ -0,0 +1,150 @@
1
+ // Copyright 2019-2025 @pezkuwi/wasm-crypto authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ use secp256k1::{
5
+ ecdsa::{RecoverableSignature, RecoveryId},
6
+ Message, PublicKey, SecretKey, SECP256K1,
7
+ };
8
+ use wasm_bindgen::prelude::*;
9
+
10
+ #[wasm_bindgen]
11
+ pub fn ext_secp_pub_compress(pubkey: &[u8]) -> Vec<u8> {
12
+ match PublicKey::from_slice(&pubkey) {
13
+ Ok(p) => p.serialize().to_vec(),
14
+ _ => panic!("Invalid pubkey provided."),
15
+ }
16
+ }
17
+
18
+ #[wasm_bindgen]
19
+ pub fn ext_secp_pub_expand(pubkey: &[u8]) -> Vec<u8> {
20
+ match PublicKey::from_slice(&pubkey) {
21
+ Ok(p) => p.serialize_uncompressed().to_vec(),
22
+ _ => panic!("Invalid pubkey provided."),
23
+ }
24
+ }
25
+
26
+ #[wasm_bindgen]
27
+ pub fn ext_secp_from_seed(seed: &[u8]) -> Vec<u8> {
28
+ match SecretKey::from_slice(seed) {
29
+ Ok(s) => {
30
+ let mut res = vec![];
31
+ let pubkey = PublicKey::from_secret_key(SECP256K1, &s);
32
+
33
+ res.extend_from_slice(&s.serialize_secret());
34
+ res.extend_from_slice(&pubkey.serialize());
35
+
36
+ res
37
+ }
38
+ _ => panic!("Invalid seed provided."),
39
+ }
40
+ }
41
+
42
+ #[wasm_bindgen]
43
+ pub fn ext_secp_recover(hash: &[u8], sig: &[u8], rec: i32) -> Vec<u8> {
44
+ match RecoveryId::from_i32(rec) {
45
+ Ok(r) => match (
46
+ Message::from_slice(hash),
47
+ RecoverableSignature::from_compact(&sig, r),
48
+ ) {
49
+ (Ok(m), Ok(s)) => {
50
+ let standard = s.to_standard();
51
+ let mut normalized = standard;
52
+ normalized.normalize_s();
53
+
54
+ // check if the signature is normalized
55
+ if normalized.ne(&standard) {
56
+ panic!("Non-normalized signature provided.");
57
+ }
58
+
59
+ match s.recover(&m) {
60
+ Ok(k) => k.serialize().to_vec(),
61
+ _ => panic!("Unable to recover."),
62
+ }
63
+ }
64
+ _ => panic!("Invalid signature provided."),
65
+ },
66
+ _ => panic!("Invalid recovery data provided."),
67
+ }
68
+ }
69
+
70
+ #[wasm_bindgen]
71
+ pub fn ext_secp_sign(hash: &[u8], seckey: &[u8]) -> Vec<u8> {
72
+ match (Message::from_slice(hash), SecretKey::from_slice(seckey)) {
73
+ (Ok(m), Ok(s)) => {
74
+ let mut res = vec![];
75
+ let (rec, sig) = SECP256K1.sign_ecdsa_recoverable(&m, &s).serialize_compact();
76
+
77
+ res.extend_from_slice(&sig);
78
+ res.push(rec.to_i32() as u8);
79
+
80
+ res
81
+ }
82
+ _ => panic!("Invalid message or secret provided."),
83
+ }
84
+ }
85
+
86
+ #[cfg(test)]
87
+ pub mod tests {
88
+ use super::*;
89
+ use hex_literal::hex;
90
+
91
+ #[test]
92
+ fn can_create_pair() {
93
+ let seckey = hex!("4380de832af797688026ce24f85204d508243f201650c1a134929e5458b7fbae");
94
+ let expected = hex!("4380de832af797688026ce24f85204d508243f201650c1a134929e5458b7fbae03fd8c74f795ced92064b86191cb2772b1e3a0947740aa0a5a6e379592471fd85b");
95
+ let res = ext_secp_from_seed(&seckey);
96
+
97
+ assert_eq!(res[..], expected[..]);
98
+ }
99
+
100
+ #[test]
101
+ fn can_pub_compress_full() {
102
+ let pubkey = hex!("04b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af");
103
+ let expected = hex!("03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077");
104
+ let res = ext_secp_pub_compress(&pubkey);
105
+
106
+ assert_eq!(res[..], expected[..]);
107
+ }
108
+
109
+ #[test]
110
+ fn can_pub_expand_comp() {
111
+ let pubkey = hex!("03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077");
112
+ let expected = hex!("04b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb1307763fe926c273235fd979a134076d00fd1683cbd35868cb485d4a3a640e52184af");
113
+ let res = ext_secp_pub_expand(&pubkey);
114
+
115
+ assert_eq!(res[..], expected[..]);
116
+ }
117
+
118
+ #[test]
119
+ fn can_recover() {
120
+ let expected = hex!("028d13da15a02f3a70677339d51b14177ee9b49657662b35e56a9d9dee17db1d30");
121
+ let sig = hex!("7505f2880114da51b3f5d535f8687953c0ab9af4ab81e592eaebebf53b728d2b6dfd9b5bcd70fee412b1f31360e7c2774009305cb84fc50c1d0ff8034dfa5fff");
122
+ let msg = hex!("a30b64ce1eedf409c8afb801d72c05234e64849ea538c15dd3c8cf4ffcf166c9");
123
+ let res = ext_secp_recover(&msg, &sig, 0);
124
+
125
+ assert_eq!(res[..], expected[..]);
126
+ }
127
+
128
+ #[test]
129
+ fn can_sign() {
130
+ // JS expectation - doesn't match?
131
+ // let expected = hex!("df92f73d9f060cefacf187b5414491cb992998ace017fa48839b5cda3e264ba8c4efa521361678d9b8582744d77aa4b8d886d7380b7808a683174afad9c4700300");
132
+ let expected = hex!("df92f73d9f060cefacf187b5414491cb992998ace017fa48839b5cda3e264ba83b105adec9e9872647a7d8bb28855b45e22805aea3d097953cbb1391f671d13e01");
133
+ let seckey = hex!("4380de832af797688026ce24f85204d508243f201650c1a134929e5458b7fbae");
134
+ let msg = hex!("68c731589a583d08b70861683b59ce3dd56284cb2f0da5b6cd83e6641dac3aab");
135
+ let res = ext_secp_sign(&msg, &seckey);
136
+
137
+ assert_eq!(res[..], expected[..]);
138
+ }
139
+
140
+ #[test]
141
+ #[should_panic(expected = "Non-normalized signature provided.")]
142
+ fn rejects_high_s_signature() {
143
+ // valid ECDSA signature with a high S value (non-normalized)
144
+ let sig = hex!(
145
+ "fa1b7a71500322d70bcd5b982c678c96c95f68893063e1621b8b85c867b80b1caae8c7c4f8b5c6d181e4c8898a3f4c329da0e2c21f6f80552a660e6c1d9fa201");
146
+ let msg = hex!("9a3c9be3a14a94df8cda1c474c0e9f8b1b35b1d85d2122cb87e6eb3c518e3be3");
147
+
148
+ let _ = ext_secp_recover(&msg, &sig, 0);
149
+ }
150
+ }