github.com/lingyao2333/mo-zero@v1.4.1/core/codec/dh.go (about) 1 package codec 2 3 import ( 4 "crypto/rand" 5 "errors" 6 "math/big" 7 ) 8 9 // see https://www.zhihu.com/question/29383090/answer/70435297 10 // see https://www.ietf.org/rfc/rfc3526.txt 11 // 2048-bit MODP Group 12 13 var ( 14 // ErrInvalidPriKey indicates the invalid private key. 15 ErrInvalidPriKey = errors.New("invalid private key") 16 // ErrInvalidPubKey indicates the invalid public key. 17 ErrInvalidPubKey = errors.New("invalid public key") 18 // ErrPubKeyOutOfBound indicates the public key is out of bound. 19 ErrPubKeyOutOfBound = errors.New("public key out of bound") 20 21 p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16) 22 g, _ = new(big.Int).SetString("2", 16) 23 zero = big.NewInt(0) 24 ) 25 26 // DhKey defines the Diffie Hellman key. 27 type DhKey struct { 28 PriKey *big.Int 29 PubKey *big.Int 30 } 31 32 // ComputeKey returns a key from public key and private key. 33 func ComputeKey(pubKey, priKey *big.Int) (*big.Int, error) { 34 if pubKey == nil { 35 return nil, ErrInvalidPubKey 36 } 37 38 if pubKey.Sign() <= 0 && p.Cmp(pubKey) <= 0 { 39 return nil, ErrPubKeyOutOfBound 40 } 41 42 if priKey == nil { 43 return nil, ErrInvalidPriKey 44 } 45 46 return new(big.Int).Exp(pubKey, priKey, p), nil 47 } 48 49 // GenerateKey returns a Diffie Hellman key. 50 func GenerateKey() (*DhKey, error) { 51 var err error 52 var x *big.Int 53 54 for { 55 x, err = rand.Int(rand.Reader, p) 56 if err != nil { 57 return nil, err 58 } 59 60 if zero.Cmp(x) < 0 { 61 break 62 } 63 } 64 65 key := new(DhKey) 66 key.PriKey = x 67 key.PubKey = new(big.Int).Exp(g, x, p) 68 69 return key, nil 70 } 71 72 // NewPublicKey returns a public key from the given bytes. 73 func NewPublicKey(bs []byte) *big.Int { 74 return new(big.Int).SetBytes(bs) 75 } 76 77 // Bytes returns public key bytes. 78 func (k *DhKey) Bytes() []byte { 79 if k.PubKey == nil { 80 return nil 81 } 82 83 byteLen := (p.BitLen() + 7) >> 3 84 ret := make([]byte, byteLen) 85 copyWithLeftPad(ret, k.PubKey.Bytes()) 86 87 return ret 88 } 89 90 func copyWithLeftPad(dst, src []byte) { 91 padBytes := len(dst) - len(src) 92 for i := 0; i < padBytes; i++ { 93 dst[i] = 0 94 } 95 copy(dst[padBytes:], src) 96 }