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  }