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  }