github.com/zntrio/harp/v2@v2.0.9/pkg/sdk/value/encryption/jwe/transformer.go (about) 1 // Licensed to Elasticsearch B.V. under one or more contributor 2 // license agreements. See the NOTICE file distributed with 3 // this work for additional information regarding copyright 4 // ownership. Elasticsearch B.V. licenses this file to you under 5 // the Apache License, Version 2.0 (the "License"); you may 6 // not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, 12 // software distributed under the License is distributed on an 13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 // KIND, either express or implied. See the License for the 15 // specific language governing permissions and limitations 16 // under the License. 17 18 package jwe 19 20 import ( 21 "context" 22 "fmt" 23 24 "gopkg.in/square/go-jose.v2" 25 26 "github.com/zntrio/harp/v2/pkg/sdk/types" 27 "github.com/zntrio/harp/v2/pkg/sdk/value" 28 ) 29 30 // PBKDF2SaltSize is the default size of the salt for PBKDF2, 128-bit salt. 31 const PBKDF2SaltSize = 16 32 33 // PBKDF2Iterations is the default number of iterations for PBKDF2, 100k 34 // iterations. Nist recommends at least 10k, 1Passsword uses 100k. 35 const PBKDF2Iterations = 500001 36 37 // transformer returns a JWE encryption transformer. 38 func transformer(key interface{}, keyAlgorithm jose.KeyAlgorithm, contentEncryption jose.ContentEncryption) (value.Transformer, error) { 39 if types.IsNil(key) { 40 return nil, fmt.Errorf("jwe: encryption key must not be nil") 41 } 42 43 // Return decorator constructor 44 return &jweTransformer{ 45 key: key, 46 keyAlgorithm: keyAlgorithm, 47 contentEncryption: contentEncryption, 48 }, nil 49 } 50 51 // ----------------------------------------------------------------------------- 52 53 type jweTransformer struct { 54 key interface{} 55 keyAlgorithm jose.KeyAlgorithm 56 contentEncryption jose.ContentEncryption 57 } 58 59 func (d *jweTransformer) To(_ context.Context, input []byte) ([]byte, error) { 60 // Prepare JOSE recipient 61 recipient := jose.Recipient{ 62 Algorithm: d.keyAlgorithm, 63 Key: d.key, 64 PBES2Count: PBKDF2Iterations, 65 } 66 67 // JWE Header 68 opts := new(jose.EncrypterOptions) 69 70 // Prepare encryption 71 encrypter, err := jose.NewEncrypter(d.contentEncryption, recipient, opts) 72 if err != nil { 73 return nil, fmt.Errorf("jwe: unable to initialize encrypter: %w", err) 74 } 75 76 // Encrypt the input 77 jwe, err := encrypter.Encrypt(input) 78 if err != nil { 79 return nil, fmt.Errorf("jwe: unable to encrypt identity keypair: %w", err) 80 } 81 82 // Assemble final JWE 83 out, err := jwe.CompactSerialize() 84 if err != nil { 85 return nil, fmt.Errorf("jwe: unable to serialize encrypted payload: %w", err) 86 } 87 88 // No error 89 return []byte(out), nil 90 } 91 92 func (d *jweTransformer) From(_ context.Context, input []byte) ([]byte, error) { 93 // Parse JWE Token 94 jwe, errParse := jose.ParseEncrypted(string(input)) 95 if errParse != nil { 96 return nil, fmt.Errorf("jwe: unable to parse JWE token") 97 } 98 99 // Try to decrypt with given passphrase 100 payload, errDecrypt := jwe.Decrypt(d.key) 101 if errDecrypt != nil { 102 return nil, fmt.Errorf("jwe: unable to decrypt JWE token") 103 } 104 105 // No error 106 return payload, nil 107 }