elliptic.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package ecdh
  2. import (
  3. "crypto"
  4. "crypto/elliptic"
  5. "io"
  6. "math/big"
  7. )
  8. type ellipticECDH struct {
  9. ECDH
  10. curve elliptic.Curve
  11. }
  12. type ellipticPublicKey struct {
  13. elliptic.Curve
  14. X, Y *big.Int
  15. }
  16. type ellipticPrivateKey struct {
  17. D []byte
  18. }
  19. // NewEllipticECDH creates a new instance of ECDH with the given elliptic.Curve curve
  20. // to use as the elliptical curve for elliptical curve diffie-hellman.
  21. func NewEllipticECDH(curve elliptic.Curve) ECDH {
  22. return &ellipticECDH{
  23. curve: curve,
  24. }
  25. }
  26. func (e *ellipticECDH) GenerateKey(rand io.Reader) (crypto.PrivateKey, crypto.PublicKey, error) {
  27. var d []byte
  28. var x, y *big.Int
  29. var priv *ellipticPrivateKey
  30. var pub *ellipticPublicKey
  31. var err error
  32. d, x, y, err = elliptic.GenerateKey(e.curve, rand)
  33. if err != nil {
  34. return nil, nil, err
  35. }
  36. priv = &ellipticPrivateKey{
  37. D: d,
  38. }
  39. pub = &ellipticPublicKey{
  40. Curve: e.curve,
  41. X: x,
  42. Y: y,
  43. }
  44. return priv, pub, nil
  45. }
  46. func (e *ellipticECDH) Marshal(p crypto.PublicKey) []byte {
  47. pub := p.(*ellipticPublicKey)
  48. return elliptic.Marshal(e.curve, pub.X, pub.Y)
  49. }
  50. func (e *ellipticECDH) Unmarshal(data []byte) (crypto.PublicKey, bool) {
  51. var key *ellipticPublicKey
  52. var x, y *big.Int
  53. x, y = elliptic.Unmarshal(e.curve, data)
  54. if x == nil || y == nil {
  55. return key, false
  56. }
  57. key = &ellipticPublicKey{
  58. Curve: e.curve,
  59. X: x,
  60. Y: y,
  61. }
  62. return key, true
  63. }
  64. // GenerateSharedSecret takes in a public key and a private key
  65. // and generates a shared secret.
  66. //
  67. // RFC5903 Section 9 states we should only return x.
  68. func (e *ellipticECDH) GenerateSharedSecret(privKey crypto.PrivateKey, pubKey crypto.PublicKey) ([]byte, error) {
  69. priv := privKey.(*ellipticPrivateKey)
  70. pub := pubKey.(*ellipticPublicKey)
  71. x, _ := e.curve.ScalarMult(pub.X, pub.Y, priv.D)
  72. return x.Bytes(), nil
  73. }