jwe.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. //go:generate ./gen.sh
  2. // Package jwe implements JWE as described in https://tools.ietf.org/html/rfc7516
  3. package jwe
  4. import (
  5. "bytes"
  6. "crypto/ecdsa"
  7. "crypto/rsa"
  8. "io"
  9. "io/ioutil"
  10. "github.com/lestrrat-go/jwx/internal/base64"
  11. "github.com/lestrrat-go/jwx/internal/json"
  12. "github.com/lestrrat-go/jwx/internal/keyconv"
  13. "github.com/lestrrat-go/jwx/jwk"
  14. "github.com/lestrrat-go/jwx/jwa"
  15. "github.com/lestrrat-go/jwx/jwe/internal/content_crypt"
  16. "github.com/lestrrat-go/jwx/jwe/internal/keyenc"
  17. "github.com/lestrrat-go/jwx/jwe/internal/keygen"
  18. "github.com/lestrrat-go/jwx/x25519"
  19. "github.com/pkg/errors"
  20. )
  21. var registry = json.NewRegistry()
  22. // Encrypt takes the plaintext payload and encrypts it in JWE compact format.
  23. // `key` should be a public key, and it may be a raw key (e.g. rsa.PublicKey) or a jwk.Key
  24. //
  25. // Encrypt currently does not support multi-recipient messages.
  26. func Encrypt(payload []byte, keyalg jwa.KeyEncryptionAlgorithm, key interface{}, contentalg jwa.ContentEncryptionAlgorithm, compressalg jwa.CompressionAlgorithm, options ...EncryptOption) ([]byte, error) {
  27. var protected Headers
  28. for _, option := range options {
  29. //nolint:forcetypeassert
  30. switch option.Ident() {
  31. case identProtectedHeader{}:
  32. protected = option.Value().(Headers)
  33. }
  34. }
  35. if protected == nil {
  36. protected = NewHeaders()
  37. }
  38. contentcrypt, err := content_crypt.NewGeneric(contentalg)
  39. if err != nil {
  40. return nil, errors.Wrap(err, `failed to create AES encrypter`)
  41. }
  42. var keyID string
  43. if jwkKey, ok := key.(jwk.Key); ok {
  44. keyID = jwkKey.KeyID()
  45. var raw interface{}
  46. if err := jwkKey.Raw(&raw); err != nil {
  47. return nil, errors.Wrapf(err, `failed to retrieve raw key out of %T`, key)
  48. }
  49. key = raw
  50. }
  51. var enc keyenc.Encrypter
  52. switch keyalg {
  53. case jwa.RSA1_5:
  54. var pubkey rsa.PublicKey
  55. if err := keyconv.RSAPublicKey(&pubkey, key); err != nil {
  56. return nil, errors.Wrapf(err, "failed to generate public key from key (%T)", key)
  57. }
  58. enc, err = keyenc.NewRSAPKCSEncrypt(keyalg, &pubkey)
  59. if err != nil {
  60. return nil, errors.Wrap(err, "failed to create RSA PKCS encrypter")
  61. }
  62. case jwa.RSA_OAEP, jwa.RSA_OAEP_256:
  63. var pubkey rsa.PublicKey
  64. if err := keyconv.RSAPublicKey(&pubkey, key); err != nil {
  65. return nil, errors.Wrapf(err, "failed to generate public key from key (%T)", key)
  66. }
  67. enc, err = keyenc.NewRSAOAEPEncrypt(keyalg, &pubkey)
  68. if err != nil {
  69. return nil, errors.Wrap(err, "failed to create RSA OAEP encrypter")
  70. }
  71. case jwa.A128KW, jwa.A192KW, jwa.A256KW,
  72. jwa.A128GCMKW, jwa.A192GCMKW, jwa.A256GCMKW,
  73. jwa.PBES2_HS256_A128KW, jwa.PBES2_HS384_A192KW, jwa.PBES2_HS512_A256KW:
  74. sharedkey, ok := key.([]byte)
  75. if !ok {
  76. return nil, errors.New("invalid key: []byte required")
  77. }
  78. switch keyalg {
  79. case jwa.A128KW, jwa.A192KW, jwa.A256KW:
  80. enc, err = keyenc.NewAES(keyalg, sharedkey)
  81. case jwa.PBES2_HS256_A128KW, jwa.PBES2_HS384_A192KW, jwa.PBES2_HS512_A256KW:
  82. enc, err = keyenc.NewPBES2Encrypt(keyalg, sharedkey)
  83. default:
  84. enc, err = keyenc.NewAESGCMEncrypt(keyalg, sharedkey)
  85. }
  86. if err != nil {
  87. return nil, errors.Wrap(err, "failed to create key wrap encrypter")
  88. }
  89. // NOTE: there was formerly a restriction, introduced
  90. // in PR #26, which disallowed certain key/content
  91. // algorithm combinations. This seemed bogus, and
  92. // interop with the jose tool demonstrates it.
  93. case jwa.ECDH_ES, jwa.ECDH_ES_A128KW, jwa.ECDH_ES_A192KW, jwa.ECDH_ES_A256KW:
  94. var keysize int
  95. switch keyalg {
  96. case jwa.ECDH_ES:
  97. // https://tools.ietf.org/html/rfc7518#page-15
  98. // In Direct Key Agreement mode, the output of the Concat KDF MUST be a
  99. // key of the same length as that used by the "enc" algorithm.
  100. keysize = contentcrypt.KeySize()
  101. case jwa.ECDH_ES_A128KW:
  102. keysize = 16
  103. case jwa.ECDH_ES_A192KW:
  104. keysize = 24
  105. case jwa.ECDH_ES_A256KW:
  106. keysize = 32
  107. }
  108. switch key := key.(type) {
  109. case x25519.PublicKey:
  110. enc, err = keyenc.NewECDHESEncrypt(keyalg, contentalg, keysize, key)
  111. default:
  112. var pubkey ecdsa.PublicKey
  113. if err := keyconv.ECDSAPublicKey(&pubkey, key); err != nil {
  114. return nil, errors.Wrapf(err, "failed to generate public key from key (%T)", key)
  115. }
  116. enc, err = keyenc.NewECDHESEncrypt(keyalg, contentalg, keysize, &pubkey)
  117. }
  118. if err != nil {
  119. return nil, errors.Wrap(err, "failed to create ECDHS key wrap encrypter")
  120. }
  121. case jwa.DIRECT:
  122. sharedkey, ok := key.([]byte)
  123. if !ok {
  124. return nil, errors.New("invalid key: []byte required")
  125. }
  126. enc, _ = keyenc.NewNoop(keyalg, sharedkey)
  127. default:
  128. return nil, errors.Errorf(`invalid key encryption algorithm (%s)`, keyalg)
  129. }
  130. if keyID != "" {
  131. enc.SetKeyID(keyID)
  132. }
  133. keysize := contentcrypt.KeySize()
  134. encctx := getEncryptCtx()
  135. defer releaseEncryptCtx(encctx)
  136. encctx.protected = protected
  137. encctx.contentEncrypter = contentcrypt
  138. encctx.generator = keygen.NewRandom(keysize)
  139. encctx.keyEncrypters = []keyenc.Encrypter{enc}
  140. encctx.compress = compressalg
  141. msg, err := encctx.Encrypt(payload)
  142. if err != nil {
  143. return nil, errors.Wrap(err, "failed to encrypt payload")
  144. }
  145. return Compact(msg)
  146. }
  147. // DecryptCtx is used internally when jwe.Decrypt is called, and is
  148. // passed for hooks that you may pass into it.
  149. //
  150. // Regular users should not have to touch this object, but if you need advanced handling
  151. // of messages, you might have to use it. Only use it when you really
  152. // understand how JWE processing works in this library.
  153. type DecryptCtx interface {
  154. Algorithm() jwa.KeyEncryptionAlgorithm
  155. SetAlgorithm(jwa.KeyEncryptionAlgorithm)
  156. Key() interface{}
  157. SetKey(interface{})
  158. Message() *Message
  159. SetMessage(*Message)
  160. }
  161. type decryptCtx struct {
  162. alg jwa.KeyEncryptionAlgorithm
  163. key interface{}
  164. msg *Message
  165. }
  166. func (ctx *decryptCtx) Algorithm() jwa.KeyEncryptionAlgorithm {
  167. return ctx.alg
  168. }
  169. func (ctx *decryptCtx) SetAlgorithm(v jwa.KeyEncryptionAlgorithm) {
  170. ctx.alg = v
  171. }
  172. func (ctx *decryptCtx) Key() interface{} {
  173. return ctx.key
  174. }
  175. func (ctx *decryptCtx) SetKey(v interface{}) {
  176. ctx.key = v
  177. }
  178. func (ctx *decryptCtx) Message() *Message {
  179. return ctx.msg
  180. }
  181. func (ctx *decryptCtx) SetMessage(m *Message) {
  182. ctx.msg = m
  183. }
  184. // Decrypt takes the key encryption algorithm and the corresponding
  185. // key to decrypt the JWE message, and returns the decrypted payload.
  186. // The JWE message can be either compact or full JSON format.
  187. //
  188. // `key` must be a private key. It can be either in its raw format (e.g. *rsa.PrivateKey) or a jwk.Key
  189. func Decrypt(buf []byte, alg jwa.KeyEncryptionAlgorithm, key interface{}, options ...DecryptOption) ([]byte, error) {
  190. var ctx decryptCtx
  191. ctx.key = key
  192. ctx.alg = alg
  193. var dst *Message
  194. var postParse PostParser
  195. //nolint:forcetypeassert
  196. for _, option := range options {
  197. switch option.Ident() {
  198. case identMessage{}:
  199. dst = option.Value().(*Message)
  200. case identPostParser{}:
  201. postParse = option.Value().(PostParser)
  202. }
  203. }
  204. msg, err := parseJSONOrCompact(buf, true)
  205. if err != nil {
  206. return nil, errors.Wrap(err, "failed to parse buffer for Decrypt")
  207. }
  208. ctx.msg = msg
  209. if postParse != nil {
  210. if err := postParse.PostParse(&ctx); err != nil {
  211. return nil, errors.Wrap(err, `failed to execute PostParser hook`)
  212. }
  213. }
  214. payload, err := doDecryptCtx(&ctx)
  215. if err != nil {
  216. return nil, errors.Wrap(err, `failed to decrypt message`)
  217. }
  218. if dst != nil {
  219. *dst = *msg
  220. dst.rawProtectedHeaders = nil
  221. dst.storeProtectedHeaders = false
  222. }
  223. return payload, nil
  224. }
  225. // Parse parses the JWE message into a Message object. The JWE message
  226. // can be either compact or full JSON format.
  227. func Parse(buf []byte) (*Message, error) {
  228. return parseJSONOrCompact(buf, false)
  229. }
  230. func parseJSONOrCompact(buf []byte, storeProtectedHeaders bool) (*Message, error) {
  231. buf = bytes.TrimSpace(buf)
  232. if len(buf) == 0 {
  233. return nil, errors.New("empty buffer")
  234. }
  235. if buf[0] == '{' {
  236. return parseJSON(buf, storeProtectedHeaders)
  237. }
  238. return parseCompact(buf, storeProtectedHeaders)
  239. }
  240. // ParseString is the same as Parse, but takes a string.
  241. func ParseString(s string) (*Message, error) {
  242. return Parse([]byte(s))
  243. }
  244. // ParseReader is the same as Parse, but takes an io.Reader.
  245. func ParseReader(src io.Reader) (*Message, error) {
  246. buf, err := ioutil.ReadAll(src)
  247. if err != nil {
  248. return nil, errors.Wrap(err, `failed to read from io.Reader`)
  249. }
  250. return Parse(buf)
  251. }
  252. func parseJSON(buf []byte, storeProtectedHeaders bool) (*Message, error) {
  253. m := NewMessage()
  254. m.storeProtectedHeaders = storeProtectedHeaders
  255. if err := json.Unmarshal(buf, &m); err != nil {
  256. return nil, errors.Wrap(err, "failed to parse JSON")
  257. }
  258. return m, nil
  259. }
  260. func parseCompact(buf []byte, storeProtectedHeaders bool) (*Message, error) {
  261. parts := bytes.Split(buf, []byte{'.'})
  262. if len(parts) != 5 {
  263. return nil, errors.Errorf(`compact JWE format must have five parts (%d)`, len(parts))
  264. }
  265. hdrbuf, err := base64.Decode(parts[0])
  266. if err != nil {
  267. return nil, errors.Wrap(err, `failed to parse first part of compact form`)
  268. }
  269. protected := NewHeaders()
  270. if err := json.Unmarshal(hdrbuf, protected); err != nil {
  271. return nil, errors.Wrap(err, "failed to parse header JSON")
  272. }
  273. ivbuf, err := base64.Decode(parts[2])
  274. if err != nil {
  275. return nil, errors.Wrap(err, "failed to base64 decode iv")
  276. }
  277. ctbuf, err := base64.Decode(parts[3])
  278. if err != nil {
  279. return nil, errors.Wrap(err, "failed to base64 decode content")
  280. }
  281. tagbuf, err := base64.Decode(parts[4])
  282. if err != nil {
  283. return nil, errors.Wrap(err, "failed to base64 decode tag")
  284. }
  285. m := NewMessage()
  286. if err := m.Set(CipherTextKey, ctbuf); err != nil {
  287. return nil, errors.Wrapf(err, `failed to set %s`, CipherTextKey)
  288. }
  289. if err := m.Set(InitializationVectorKey, ivbuf); err != nil {
  290. return nil, errors.Wrapf(err, `failed to set %s`, InitializationVectorKey)
  291. }
  292. if err := m.Set(ProtectedHeadersKey, protected); err != nil {
  293. return nil, errors.Wrapf(err, `failed to set %s`, ProtectedHeadersKey)
  294. }
  295. if err := m.makeDummyRecipient(string(parts[1]), protected); err != nil {
  296. return nil, errors.Wrap(err, `failed to setup recipient`)
  297. }
  298. if err := m.Set(TagKey, tagbuf); err != nil {
  299. return nil, errors.Wrapf(err, `failed to set %s`, TagKey)
  300. }
  301. if storeProtectedHeaders {
  302. // This is later used for decryption.
  303. m.rawProtectedHeaders = parts[0]
  304. }
  305. return m, nil
  306. }
  307. // RegisterCustomField allows users to specify that a private field
  308. // be decoded as an instance of the specified type. This option has
  309. // a global effect.
  310. //
  311. // For example, suppose you have a custom field `x-birthday`, which
  312. // you want to represent as a string formatted in RFC3339 in JSON,
  313. // but want it back as `time.Time`.
  314. //
  315. // In that case you would register a custom field as follows
  316. //
  317. // jwe.RegisterCustomField(`x-birthday`, timeT)
  318. //
  319. // Then `hdr.Get("x-birthday")` will still return an `interface{}`,
  320. // but you can convert its type to `time.Time`
  321. //
  322. // bdayif, _ := hdr.Get(`x-birthday`)
  323. // bday := bdayif.(time.Time)
  324. func RegisterCustomField(name string, object interface{}) {
  325. registry.Register(name, object)
  326. }