keygen.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. package keygen
  2. import (
  3. "crypto"
  4. "crypto/ecdsa"
  5. "crypto/rand"
  6. "encoding/binary"
  7. "io"
  8. "golang.org/x/crypto/curve25519"
  9. "github.com/lestrrat-go/jwx/internal/ecutil"
  10. "github.com/lestrrat-go/jwx/jwa"
  11. "github.com/lestrrat-go/jwx/jwe/internal/concatkdf"
  12. "github.com/lestrrat-go/jwx/jwk"
  13. "github.com/lestrrat-go/jwx/x25519"
  14. "github.com/pkg/errors"
  15. )
  16. // Bytes returns the byte from this ByteKey
  17. func (k ByteKey) Bytes() []byte {
  18. return []byte(k)
  19. }
  20. // Size returns the size of the key
  21. func (g Static) Size() int {
  22. return len(g)
  23. }
  24. // Generate returns the key
  25. func (g Static) Generate() (ByteSource, error) {
  26. buf := make([]byte, g.Size())
  27. copy(buf, g)
  28. return ByteKey(buf), nil
  29. }
  30. // NewRandom creates a new Generator that returns
  31. // random bytes
  32. func NewRandom(n int) Random {
  33. return Random{keysize: n}
  34. }
  35. // Size returns the key size
  36. func (g Random) Size() int {
  37. return g.keysize
  38. }
  39. // Generate generates a random new key
  40. func (g Random) Generate() (ByteSource, error) {
  41. buf := make([]byte, g.keysize)
  42. if _, err := io.ReadFull(rand.Reader, buf); err != nil {
  43. return nil, errors.Wrap(err, "failed to read from rand.Reader")
  44. }
  45. return ByteKey(buf), nil
  46. }
  47. // NewEcdhes creates a new key generator using ECDH-ES
  48. func NewEcdhes(alg jwa.KeyEncryptionAlgorithm, enc jwa.ContentEncryptionAlgorithm, keysize int, pubkey *ecdsa.PublicKey) (*Ecdhes, error) {
  49. return &Ecdhes{
  50. algorithm: alg,
  51. enc: enc,
  52. keysize: keysize,
  53. pubkey: pubkey,
  54. }, nil
  55. }
  56. // Size returns the key size associated with this generator
  57. func (g Ecdhes) Size() int {
  58. return g.keysize
  59. }
  60. // Generate generates new keys using ECDH-ES
  61. func (g Ecdhes) Generate() (ByteSource, error) {
  62. priv, err := ecdsa.GenerateKey(g.pubkey.Curve, rand.Reader)
  63. if err != nil {
  64. return nil, errors.Wrap(err, "failed to generate key for ECDH-ES")
  65. }
  66. var algorithm string
  67. if g.algorithm == jwa.ECDH_ES {
  68. algorithm = g.enc.String()
  69. } else {
  70. algorithm = g.algorithm.String()
  71. }
  72. pubinfo := make([]byte, 4)
  73. binary.BigEndian.PutUint32(pubinfo, uint32(g.keysize)*8)
  74. z, _ := priv.PublicKey.Curve.ScalarMult(g.pubkey.X, g.pubkey.Y, priv.D.Bytes())
  75. zBytes := ecutil.AllocECPointBuffer(z, priv.PublicKey.Curve)
  76. defer ecutil.ReleaseECPointBuffer(zBytes)
  77. kdf := concatkdf.New(crypto.SHA256, []byte(algorithm), zBytes, []byte{}, []byte{}, pubinfo, []byte{})
  78. kek := make([]byte, g.keysize)
  79. if _, err := kdf.Read(kek); err != nil {
  80. return nil, errors.Wrap(err, "failed to read kdf")
  81. }
  82. return ByteWithECPublicKey{
  83. PublicKey: &priv.PublicKey,
  84. ByteKey: ByteKey(kek),
  85. }, nil
  86. }
  87. // NewX25519 creates a new key generator using ECDH-ES
  88. func NewX25519(alg jwa.KeyEncryptionAlgorithm, enc jwa.ContentEncryptionAlgorithm, keysize int, pubkey x25519.PublicKey) (*X25519, error) {
  89. return &X25519{
  90. algorithm: alg,
  91. enc: enc,
  92. keysize: keysize,
  93. pubkey: pubkey,
  94. }, nil
  95. }
  96. // Size returns the key size associated with this generator
  97. func (g X25519) Size() int {
  98. return g.keysize
  99. }
  100. // Generate generates new keys using ECDH-ES
  101. func (g X25519) Generate() (ByteSource, error) {
  102. pub, priv, err := x25519.GenerateKey(rand.Reader)
  103. if err != nil {
  104. return nil, errors.Wrap(err, "failed to generate key for X25519")
  105. }
  106. var algorithm string
  107. if g.algorithm == jwa.ECDH_ES {
  108. algorithm = g.enc.String()
  109. } else {
  110. algorithm = g.algorithm.String()
  111. }
  112. pubinfo := make([]byte, 4)
  113. binary.BigEndian.PutUint32(pubinfo, uint32(g.keysize)*8)
  114. zBytes, err := curve25519.X25519(priv.Seed(), g.pubkey)
  115. if err != nil {
  116. return nil, errors.Wrap(err, "failed to compute Z")
  117. }
  118. kdf := concatkdf.New(crypto.SHA256, []byte(algorithm), zBytes, []byte{}, []byte{}, pubinfo, []byte{})
  119. kek := make([]byte, g.keysize)
  120. if _, err := kdf.Read(kek); err != nil {
  121. return nil, errors.Wrap(err, "failed to read kdf")
  122. }
  123. return ByteWithECPublicKey{
  124. PublicKey: pub,
  125. ByteKey: ByteKey(kek),
  126. }, nil
  127. }
  128. // HeaderPopulate populates the header with the required EC-DSA public key
  129. // information ('epk' key)
  130. func (k ByteWithECPublicKey) Populate(h Setter) error {
  131. key, err := jwk.New(k.PublicKey)
  132. if err != nil {
  133. return errors.Wrap(err, "failed to create JWK")
  134. }
  135. if err := h.Set("epk", key); err != nil {
  136. return errors.Wrap(err, "failed to write header")
  137. }
  138. return nil
  139. }
  140. // HeaderPopulate populates the header with the required AES GCM
  141. // parameters ('iv' and 'tag')
  142. func (k ByteWithIVAndTag) Populate(h Setter) error {
  143. if err := h.Set("iv", k.IV); err != nil {
  144. return errors.Wrap(err, "failed to write header")
  145. }
  146. if err := h.Set("tag", k.Tag); err != nil {
  147. return errors.Wrap(err, "failed to write header")
  148. }
  149. return nil
  150. }
  151. // HeaderPopulate populates the header with the required PBES2
  152. // parameters ('p2s' and 'p2c')
  153. func (k ByteWithSaltAndCount) Populate(h Setter) error {
  154. if err := h.Set("p2c", k.Count); err != nil {
  155. return errors.Wrap(err, "failed to write header")
  156. }
  157. if err := h.Set("p2s", k.Salt); err != nil {
  158. return errors.Wrap(err, "failed to write header")
  159. }
  160. return nil
  161. }