x25519.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. package x25519
  2. import (
  3. "bytes"
  4. "crypto"
  5. cryptorand "crypto/rand"
  6. "io"
  7. "golang.org/x/crypto/curve25519"
  8. "github.com/pkg/errors"
  9. )
  10. // This mirrors ed25519's structure for private/public "keys". jwx
  11. // requires dedicated types for these as they drive
  12. // serialization/deserialization logic, as well as encryption types.
  13. //
  14. // Note that with the x25519 scheme, the private key is a sequence of
  15. // 32 bytes, while the public key is the result of X25519(private,
  16. // basepoint).
  17. //
  18. // Portions of this file are from Go's ed25519.go, which is
  19. // Copyright 2016 The Go Authors. All rights reserved.
  20. const (
  21. // PublicKeySize is the size, in bytes, of public keys as used in this package.
  22. PublicKeySize = 32
  23. // PrivateKeySize is the size, in bytes, of private keys as used in this package.
  24. PrivateKeySize = 64
  25. // SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
  26. SeedSize = 32
  27. )
  28. // PublicKey is the type of X25519 public keys
  29. type PublicKey []byte
  30. // Any methods implemented on PublicKey might need to also be implemented on
  31. // PrivateKey, as the latter embeds the former and will expose its methods.
  32. // Equal reports whether pub and x have the same value.
  33. func (pub PublicKey) Equal(x crypto.PublicKey) bool {
  34. xx, ok := x.(PublicKey)
  35. if !ok {
  36. return false
  37. }
  38. return bytes.Equal(pub, xx)
  39. }
  40. // PrivateKey is the type of X25519 private key
  41. type PrivateKey []byte
  42. // Public returns the PublicKey corresponding to priv.
  43. func (priv PrivateKey) Public() crypto.PublicKey {
  44. publicKey := make([]byte, PublicKeySize)
  45. copy(publicKey, priv[SeedSize:])
  46. return PublicKey(publicKey)
  47. }
  48. // Equal reports whether priv and x have the same value.
  49. func (priv PrivateKey) Equal(x crypto.PrivateKey) bool {
  50. xx, ok := x.(PrivateKey)
  51. if !ok {
  52. return false
  53. }
  54. return bytes.Equal(priv, xx)
  55. }
  56. // Seed returns the private key seed corresponding to priv. It is provided for
  57. // interoperability with RFC 7748. RFC 7748's private keys correspond to seeds
  58. // in this package.
  59. func (priv PrivateKey) Seed() []byte {
  60. seed := make([]byte, SeedSize)
  61. copy(seed, priv[:SeedSize])
  62. return seed
  63. }
  64. // NewKeyFromSeed calculates a private key from a seed. It will return
  65. // an error if len(seed) is not SeedSize. This function is provided
  66. // for interoperability with RFC 7748. RFC 7748's private keys
  67. // correspond to seeds in this package.
  68. func NewKeyFromSeed(seed []byte) (PrivateKey, error) {
  69. privateKey := make([]byte, PrivateKeySize)
  70. if len(seed) != SeedSize {
  71. return nil, errors.Errorf("unexpected seed size: %d", len(seed))
  72. }
  73. copy(privateKey, seed)
  74. public, err := curve25519.X25519(seed, curve25519.Basepoint)
  75. if err != nil {
  76. return nil, errors.Wrap(err, "failed to compute public key")
  77. }
  78. copy(privateKey[SeedSize:], public)
  79. return privateKey, nil
  80. }
  81. // GenerateKey generates a public/private key pair using entropy from rand.
  82. // If rand is nil, crypto/rand.Reader will be used.
  83. func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
  84. if rand == nil {
  85. rand = cryptorand.Reader
  86. }
  87. seed := make([]byte, SeedSize)
  88. if _, err := io.ReadFull(rand, seed); err != nil {
  89. return nil, nil, err
  90. }
  91. privateKey, err := NewKeyFromSeed(seed)
  92. if err != nil {
  93. return nil, nil, err
  94. }
  95. publicKey := make([]byte, PublicKeySize)
  96. copy(publicKey, privateKey[SeedSize:])
  97. return publicKey, privateKey, nil
  98. }