|
1 | 1 | pragma solidity ^0.8.0;
|
2 | 2 |
|
3 | 3 | library Secp256r1 {
|
4 |
| - uint256 constant ORDER = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551; |
| 4 | + address internal constant ECMUL_ADDR = 0x0000000000000000000000000000000000070700; |
| 5 | + uint256 internal constant ORDER = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551; |
| 6 | + uint256 internal constant G_X = 0x6b17d1f2_e12c4247_f8bce6e5_63a440f2_77037d81_2deb33a0_f4a13945_d898c296; |
| 7 | + uint256 internal constant G_Y = 0x4fe342e2_fe1a7f9b_8ee7eb4a_7c0f9e16_2bce3357_6b315ece_cbb64068_37bf51f5; |
| 8 | + |
| 9 | + struct Point { |
| 10 | + uint256 x; |
| 11 | + uint256 y; |
| 12 | + } |
5 | 13 |
|
6 | 14 | function isScalar(uint256 scalar) internal pure returns (bool) {
|
7 | 15 | return scalar > 0 && scalar < ORDER;
|
8 | 16 | }
|
9 | 17 |
|
10 |
| - function encodeScalarPkcs8Der(uint256 scalar) internal pure returns (bytes memory) { |
| 18 | + function publicKey(uint256 sk) internal view returns (Point memory) { |
| 19 | + return ecmul(G_X, G_Y, sk); |
| 20 | + } |
| 21 | + |
| 22 | + function encodePkcs8Der(uint256 sk, Point memory pk) internal pure returns (bytes memory) { |
11 | 23 | // PrivateKeyInfo ::= SEQUENCE {
|
12 | 24 | // version Version,
|
13 | 25 | // privateKeyAlgorithm AlgorithmIdentifier,
|
14 | 26 | // privateKey OCTET STRING,
|
15 | 27 | // attributes [0] IMPLICIT Attributes OPTIONAL }
|
16 | 28 | //
|
17 |
| - // 30 81 41 ; SEQUENCE (0x41 bytes) |
| 29 | + // 30 81 87 ; SEQUENCE (0x87 bytes) |
18 | 30 | // 02 01 00 ; INTEGER (0)
|
19 | 31 | // 30 13 ; SEQUENCE (0x13 bytes)
|
20 |
| - // 06 07 ; OBJECT IDENTIFIER (ecdsaWithSHA1) |
| 32 | + // 06 07 ; OBJECT IDENTIFIER (ecPublicKey) |
21 | 33 | // 2A 86 48 CE 3D 02 01
|
22 | 34 | // 06 08 ; OBJECT IDENTIFIER (prime256v1)
|
23 | 35 | // 2A 86 48 CE 3D 03 01 07
|
24 |
| - // 04 27 ; OCTET STRING (0x27 bytes) |
25 |
| - // 30 25 ; SEQUENCE (0x25 bytes) |
| 36 | + // 04 6d ; OCTET STRING (0x6d bytes) |
| 37 | + // 30 6b ; SEQUENCE (0x6b bytes) |
26 | 38 | // 02 01 01 ; INTEGER (1)
|
27 | 39 | // 04 20 ; OCTET STRING (32 bytes)
|
28 | 40 | // <32 byte private key>
|
29 |
| - return |
30 |
| - bytes.concat(hex"308141020100301306072a8648ce3d020106082a8648ce3d030107042730250201010420", bytes32(scalar)); |
| 41 | + // a1 44 ; Attribute (0x44 bytes) |
| 42 | + // 03 42 ; BIT STRING (0x42 bytes) |
| 43 | + // 00 <sec1 encoded public key> |
| 44 | + return bytes.concat( |
| 45 | + hex"308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420", |
| 46 | + bytes32(sk), |
| 47 | + hex"a14403420004", |
| 48 | + bytes32(pk.x), |
| 49 | + bytes32(pk.y) |
| 50 | + ); |
| 51 | + } |
| 52 | + |
| 53 | + function ecmul(uint256 x, uint256 y, uint256 s) internal view returns (Point memory) { |
| 54 | + (bool success, bytes memory result) = ECMUL_ADDR.staticcall(abi.encode(x, y, s)); |
| 55 | + require(success); |
| 56 | + return abi.decode(result, (Point)); |
31 | 57 | }
|
32 | 58 | }
|
0 commit comments