src/crypto/secp256k1.bend
bend-collections-laws-crypto@1.0.0.0 · 117 lines · 19 definitions
1import Base
2import bend-collections-laws-crypto@1.0.0.0/src/crypto/secp256k1/ecdsa.bend as E
3import bend-collections-laws-crypto@1.0.0.0/src/crypto/secp256k1/schnorr.bend as Sch
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
39type Keypair is Data:
40 Keypair{secret: List<&2, U32>, public: List<&2, U32>}
41
42def keypair_of(+seed: List<&2, U32>, m: Maybe<&2, List<&2, U32>>) -> Maybe<&2, Keypair>:
43 match m:
44 case None{}: None{}
45 case Some{pk}: Some{Keypair{seed, pk}}
46
47def generate_keypair(+seed: List<&2, U32>) -> Maybe<&2, Keypair>:
48 keypair_of(seed, E.public_key(seed, True{}))
49
50def word_bytes(+w: U32, rest: List<&2, U32>) -> List<&2, U32>:
51 U32.and(w, 255) <> U32.and(U32.shrn(w, 8n), 255) <> U32.and(U32.shrn(w, 16n), 255) <> U32.shrn(w, 24n) <> rest
52
53def random_bytes(n: Nat, acc: List<&2, U32>) -> IO(List<&2, U32>):
54 match n:
55 case 0n:
56 IO.pure(List<&2, U32>, acc)
57 case 1n+m:
58 do IO<List<&2, U32>>:
59 w : U32 <- IO.try(U32, IO.random_u32())
60 rest : List<&2, U32> <- random_bytes(m, acc)
61 return word_bytes(w, rest)
62
63def os_retry(fuel: Nat, m: Maybe<&2, Keypair>) -> IO(Maybe<&2, Keypair>):
64 match fuel m:
65 case _ Some{kp}:
66 IO.pure(Maybe<&2, Keypair>, Some{kp})
67 case 0n None{}:
68 IO.pure(Maybe<&2, Keypair>, None{})
69 case 1n+f None{}:
70 do IO<Maybe<&2, Keypair>>:
71 seed : List<&2, U32> <- random_bytes(8n, Nil{})
72 kp : Maybe<&2, Keypair> <- os_retry(f, generate_keypair(seed))
73 return kp
74
75
76
77
78def generate_keypair_os() -> IO(Maybe<&2, Keypair>):
79 os_retry(8n, None{})
80
81def public_key(+sk: List<&2, U32>, compressed: Bool) -> Maybe<&2, List<&2, U32>>:
82 E.public_key(sk, compressed)
83
84def sign(+sk: List<&2, U32>, +hash: List<&2, U32>) -> Maybe<&2, E.Signature>:
85 E.sign(sk, hash)
86
87def compact(m: Maybe<&2, E.Signature>) -> Maybe<&2, List<&2, U32>>:
88 match m:
89 case None{}: None{}
90 case Some{E.Signature{r, s, v}}: Some{List.append(&2, U32, r, List.append(&2, U32, s, [v]))}
91
92def sign_compact(+sk: List<&2, U32>, +hash: List<&2, U32>) -> Maybe<&2, List<&2, U32>>:
93 compact(E.sign(sk, hash))
94
95def verify(+pk: List<&2, U32>, +hash: List<&2, U32>, +sig: List<&2, U32>) -> Bool:
96 E.verify(pk, hash, sig)
97
98def verify_strict(+pk: List<&2, U32>, +hash: List<&2, U32>, +sig: List<&2, U32>) -> Bool:
99 E.verify_strict(pk, hash, sig)
100
101def recover(+hash: List<&2, U32>, +sig: List<&2, U32>) -> Maybe<&2, List<&2, U32>>:
102 E.recover(hash, sig)
103
104def eth_address(+pk: List<&2, U32>) -> Maybe<&2, List<&2, U32>>:
105 E.eth_address(pk)
106
107def ecrecover(input: List<&2, U32>) -> Maybe<&2, List<&2, U32>>:
108 E.ecrecover(input)
109
110def schnorr_pubkey(+sk: List<&2, U32>) -> Maybe<&2, List<&2, U32>>:
111 Sch.pubkey(sk)
112
113def schnorr_sign(+sk: List<&2, U32>, +msg: List<&2, U32>, +aux: List<&2, U32>) -> Maybe<&2, List<&2, U32>>:
114 Sch.sign(sk, msg, aux)
115
116def schnorr_verify(+pk: List<&2, U32>, +msg: List<&2, U32>, +sig: List<&2, U32>) -> Bool:
117 Sch.verify(pk, msg, sig)