dh.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. package codec
  2. import (
  3. "crypto/rand"
  4. "errors"
  5. "math/big"
  6. )
  7. // see https://www.zhihu.com/question/29383090/answer/70435297
  8. // see https://www.ietf.org/rfc/rfc3526.txt
  9. // 2048-bit MODP Group
  10. var (
  11. ErrInvalidPriKey = errors.New("invalid private key")
  12. ErrInvalidPubKey = errors.New("invalid public key")
  13. ErrPubKeyOutOfBound = errors.New("public key out of bound")
  14. p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
  15. g, _ = new(big.Int).SetString("2", 16)
  16. zero = big.NewInt(0)
  17. )
  18. type DhKey struct {
  19. PriKey *big.Int
  20. PubKey *big.Int
  21. }
  22. func ComputeKey(pubKey, priKey *big.Int) (*big.Int, error) {
  23. if pubKey == nil {
  24. return nil, ErrInvalidPubKey
  25. }
  26. if pubKey.Sign() <= 0 && p.Cmp(pubKey) <= 0 {
  27. return nil, ErrPubKeyOutOfBound
  28. }
  29. if priKey == nil {
  30. return nil, ErrInvalidPriKey
  31. }
  32. return new(big.Int).Exp(pubKey, priKey, p), nil
  33. }
  34. func GenerateKey() (*DhKey, error) {
  35. var err error
  36. var x *big.Int
  37. for {
  38. x, err = rand.Int(rand.Reader, p)
  39. if err != nil {
  40. return nil, err
  41. }
  42. if zero.Cmp(x) < 0 {
  43. break
  44. }
  45. }
  46. key := new(DhKey)
  47. key.PriKey = x
  48. key.PubKey = new(big.Int).Exp(g, x, p)
  49. return key, nil
  50. }
  51. func NewPublicKey(bs []byte) *big.Int {
  52. return new(big.Int).SetBytes(bs)
  53. }
  54. func (k *DhKey) Bytes() []byte {
  55. if k.PubKey == nil {
  56. return nil
  57. }
  58. byteLen := (p.BitLen() + 7) >> 3
  59. ret := make([]byte, byteLen)
  60. copyWithLeftPad(ret, k.PubKey.Bytes())
  61. return ret
  62. }
  63. func copyWithLeftPad(dst, src []byte) {
  64. padBytes := len(dst) - len(src)
  65. for i := 0; i < padBytes; i++ {
  66. dst[i] = 0
  67. }
  68. copy(dst[padBytes:], src)
  69. }