carlos / contra Public

Clone
git clone https://amadan.net/carlos/contra

Plain git — no account needed to clone.

Download

Download this file

1package crypto
2
3import (
4 "crypto/ecdh"
5 "errors"
6)
7
8// ErrNoScalar means the rejection loop ran out of counter values. At a
9// rejection probability of about 2^-32 per candidate this cannot happen by
10// chance; it means the seed or the label is wrong.
11var ErrNoScalar = errors.New("crypto: no valid P-256 scalar in 256 candidates")
12
13// DeriveP256 turns a 32-byte seed into the deterministic P-256 signing keypair
14// the server authenticates by signed challenge — it stores only the public
15// half, so a fully compromised server holds something that cannot decrypt and
16// cannot be replayed.
17//
18// Rejection sampling, because a uniform 32-byte string is not a uniform scalar
19// mod n. ecdh.NewPrivateKey does the range check for us: it accepts exactly
20// [1, n-1]. A rejection is a ~2^-32 event, so the loop past i=0 is only ever
21// reached by the searched seed in the vector file.
22func DeriveP256(seed []byte) (*ecdh.PrivateKey, error) {
23 info := make([]byte, len(LabelECP256)+1)
24 copy(info, LabelECP256)
25
26 for i := 0; i < 256; i++ {
27 info[len(info)-1] = byte(i)
28 candidate, err := Derive(seed, nil, string(info), 32)
29 if err != nil {
30 return nil, err
31 }
32 key, err := ecdh.P256().NewPrivateKey(candidate)
33 if err == nil {
34 return key, nil
35 }
36 }
37 return nil, ErrNoScalar
38}
39