···11+module K256 = struct
22+ open Hacl_star.Hacl
33+44+ let sign ~privkey ~msg : bytes =
55+ let hashed = SHA2_256.hash msg in
66+ let k = Rfc6979.k_for_k256 ~privkey ~msg in
77+ match K256.Libsecp256k1.sign ~sk:privkey ~msg:hashed ~k with
88+ | Some signature ->
99+ signature
1010+ | None ->
1111+ failwith "failed to sign message"
1212+1313+ let verify ~pubkey ~msg ~signature : bool =
1414+ let hashed = SHA2_256.hash msg in
1515+ K256.Libsecp256k1.verify ~pk:pubkey ~msg:hashed ~signature
1616+end
1717+1818+module P256 = struct
1919+ open Hacl_star.Hacl
2020+2121+ let sign ~privkey ~msg : bytes =
2222+ let hashed = SHA2_256.hash msg in
2323+ let k = Rfc6979.k_for_p256 ~privkey ~msg in
2424+ match P256.sign ~sk:privkey ~msg:hashed ~k with
2525+ | Some signature ->
2626+ signature
2727+ | None ->
2828+ failwith "failed to sign message"
2929+3030+ let verify ~pubkey ~msg ~signature : bool =
3131+ let hashed = SHA2_256.hash msg in
3232+ P256.verify ~pk:pubkey ~msg:hashed ~signature
3333+end
+132
kleidos/rfc6979.ml
···11+(* rfc 6979 nonce "k" generation *)
22+33+(* curve orders *)
44+let n_secp256k1 =
55+ Z.of_string_base 16
66+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
77+88+let n_secp256r1 =
99+ Z.of_string_base 16
1010+ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"
1111+1212+(* 32-byte big-endian to Z *)
1313+let bytes32_to_z (b : bytes) : Z.t =
1414+ if Bytes.length b <> 32 then invalid_arg "expected 32 bytes" ;
1515+ Bytes.fold_left
1616+ (fun acc c -> Z.(add (shift_left acc 8) (of_int (Char.code c))))
1717+ Z.zero b
1818+1919+(* Z to fixed 32-byte big-endian *)
2020+let z_to_bytes32 (z : Z.t) : bytes =
2121+ let out = Bytes.make 32 '\x00' in
2222+ let rec fill i v =
2323+ if i < 0 || v = Z.zero then ()
2424+ else (
2525+ Bytes.set out i (Char.chr Z.(to_int (logand v (of_int 0xFF)))) ;
2626+ fill (i - 1) Z.(shift_right v 8) )
2727+ in
2828+ fill 31 z ;
2929+ if z >= Z.(shift_left one 256) then invalid_arg "integer too large" ;
3030+ out
3131+3232+(* bits2int for qbits=256 (leftmost 256 bits is whole 32 bytes here) *)
3333+let bits2int_256 (bs : bytes) : Z.t =
3434+ (* If bs > 32 bytes (not the case here), we'd truncate *)
3535+ let len = Bytes.length bs in
3636+ let take = if len <= 32 then len else 32 in
3737+ let acc = ref Z.zero in
3838+ for i = 0 to take - 1 do
3939+ acc := Z.(add (shift_left !acc 8) (of_int (Char.code (Bytes.get bs i))))
4040+ done ;
4141+ if len > 32 then
4242+ (* shift right extra bits if longer (not expected with SHA-256) *)
4343+ let extra_bits = (len - 32) * 8 in
4444+ Z.shift_right !acc extra_bits
4545+ else !acc
4646+4747+(* bits2octets per RFC 6979 §2.3.2: reduce hash to scalar-sized octets *)
4848+let bits2octets_256 ~q h1 =
4949+ let z1 = bits2int_256 h1 in
5050+ let z2 = Z.(z1 mod q) in
5151+ z_to_bytes32 z2
5252+5353+(* hmac sha256 using only hash function *)
5454+let hmac_sha256 ~(hash : bytes -> bytes) ~(key : bytes) (data : bytes) : bytes =
5555+ let block_size = 64 in
5656+ let key0 = if Bytes.length key > block_size then hash key else key in
5757+ let key_block =
5858+ if Bytes.length key0 = block_size then key0
5959+ else
6060+ let b = Bytes.make block_size '\x00' in
6161+ Bytes.blit key0 0 b 0 (Bytes.length key0) ;
6262+ b
6363+ in
6464+ let ipad = 0x36 and opad = 0x5c in
6565+ let inner_pad = Bytes.create block_size
6666+ and outer_pad = Bytes.create block_size in
6767+ for i = 0 to block_size - 1 do
6868+ let kc = Char.code (Bytes.get key_block i) in
6969+ Bytes.set inner_pad i (Char.chr (kc lxor ipad)) ;
7070+ Bytes.set outer_pad i (Char.chr (kc lxor opad))
7171+ done ;
7272+ let concat a b =
7373+ let out = Bytes.create (Bytes.length a + Bytes.length b) in
7474+ Bytes.blit a 0 out 0 (Bytes.length a) ;
7575+ Bytes.blit b 0 out (Bytes.length a) (Bytes.length b) ;
7676+ out
7777+ in
7878+ let inner = hash (concat inner_pad data) in
7979+ hash (concat outer_pad inner)
8080+8181+(* returns 32-byte k for given order q *)
8282+let rfc6979_k_256_bytes ~(q : Z.t) ~(privkey : bytes) ~(msg : bytes) : bytes =
8383+ if Bytes.length privkey <> 32 then invalid_arg "privkey must be 32 bytes" ;
8484+ let x = bytes32_to_z privkey in
8585+ if x <= Z.zero || x >= q then invalid_arg "privkey scalar out of range" ;
8686+ let module H = Hacl_star.Hacl.SHA2_256 in
8787+ let hash = H.hash in
8888+ let hmac = hmac_sha256 ~hash in
8989+ let h1 = hash msg in
9090+ (* 32-byte SHA-256 digest *)
9191+ let x_octets = privkey in
9292+ (* already 32 bytes big-endian *)
9393+ let h1_red = bits2octets_256 ~q h1 in
9494+ let v = Bytes.make 32 '\x01' in
9595+ let k = Bytes.make 32 '\x00' in
9696+ let concat parts =
9797+ let total = List.fold_left (fun a b -> a + Bytes.length b) 0 parts in
9898+ let out = Bytes.create total in
9999+ ignore
100100+ @@ List.fold_left
101101+ (fun off b ->
102102+ Bytes.blit b 0 out off (Bytes.length b) ;
103103+ off + Bytes.length b )
104104+ 0 parts ;
105105+ out
106106+ in
107107+ (* step: K = HMAC_K(V || 0x00 || x || h1); V = HMAC_K(V) *)
108108+ let k = hmac ~key:k (concat [v; Bytes.of_string "\x00"; x_octets; h1_red]) in
109109+ let v = hmac ~key:k v in
110110+ (* step: K = HMAC_K(V || 0x01 || x || h1); V = HMAC_K(V) *)
111111+ let k = hmac ~key:k (concat [v; Bytes.of_string "\x01"; x_octets; h1_red]) in
112112+ let v = hmac ~key:k v in
113113+ (* loop *)
114114+ let rec loop k v =
115115+ (* a. V = HMAC_K(V) *)
116116+ let v = hmac ~key:k v in
117117+ let t = v in
118118+ let k_candidate = bits2int_256 t in
119119+ if Z.(k_candidate >= one && k_candidate < q) then t
120120+ else
121121+ (* K = HMAC_K(V || 0x00); V = HMAC_K(V) *)
122122+ let k = hmac ~key:k (concat [v; Bytes.of_string "\x00"]) in
123123+ let v = hmac ~key:k v in
124124+ loop k v
125125+ in
126126+ loop k v
127127+128128+let k_for_k256 ~(privkey : bytes) ~(msg : bytes) : bytes =
129129+ rfc6979_k_256_bytes ~q:n_secp256k1 ~privkey ~msg
130130+131131+let k_for_p256 ~(privkey : bytes) ~(msg : bytes) : bytes =
132132+ rfc6979_k_256_bytes ~q:n_secp256r1 ~privkey ~msg