github.com/zntrio/harp/v2@v2.0.9/pkg/sdk/value/encryption/aead/builders.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 aead 19 20 import ( 21 "crypto/aes" 22 "crypto/cipher" 23 "encoding/base64" 24 "fmt" 25 "strings" 26 27 miscreant "github.com/miscreant/miscreant.go" 28 29 "github.com/zntrio/harp/v2/build/fips" 30 "github.com/zntrio/harp/v2/pkg/sdk/value" 31 "github.com/zntrio/harp/v2/pkg/sdk/value/encryption" 32 33 "golang.org/x/crypto/chacha20poly1305" 34 ) 35 36 var ( 37 aesgcmPrefix = "aes-gcm" 38 aespmacsivPrefix = "aes-pmac-siv" 39 aessivPrefix = "aes-siv" 40 chachaPrefix = "chacha" 41 xchachaPrefix = "xchacha" 42 ) 43 44 func init() { 45 encryption.Register(aesgcmPrefix, AESGCM) 46 47 if !fips.Enabled() { 48 encryption.Register(aespmacsivPrefix, AESPMACSIV) 49 encryption.Register(aessivPrefix, AESSIV) 50 encryption.Register(chachaPrefix, Chacha20Poly1305) 51 encryption.Register(xchachaPrefix, XChacha20Poly1305) 52 } 53 } 54 55 // AESGCM returns an AES-GCM value transformer instance. 56 func AESGCM(key string) (value.Transformer, error) { 57 // Remove the prefix 58 key = strings.TrimPrefix(key, "aes-gcm:") 59 60 // Decode key 61 k, err := base64.URLEncoding.DecodeString(key) 62 if err != nil { 63 return nil, fmt.Errorf("aes: unable to decode transformer key: %w", err) 64 } 65 66 // Check key length 67 switch len(k) { 68 case 16, 24, 32: 69 default: 70 return nil, fmt.Errorf("aes: invalid key length, use 16 bytes (AES128) or 24 bytes (AES192) or 32 bytes (AES256)") 71 } 72 73 // Create AES block cipher 74 block, err := aes.NewCipher(k) 75 if err != nil { 76 return nil, fmt.Errorf("aes: unable to initialize block cipher: %w", err) 77 } 78 79 // Initialize AEAD cipher chain 80 aead, err := cipher.NewGCM(block) 81 if err != nil { 82 return nil, fmt.Errorf("aes: unable to initialize aead chain : %w", err) 83 } 84 85 // Return transformer 86 return &aeadTransformer{ 87 aead: aead, 88 }, nil 89 } 90 91 // AESSIV returns an AES-SIV/AES-CMAC-SIV value transformer instance. 92 func AESSIV(key string) (value.Transformer, error) { 93 // Remove the prefix 94 key = strings.TrimPrefix(key, "aes-siv:") 95 96 // Decode key 97 k, err := base64.URLEncoding.DecodeString(key) 98 if err != nil { 99 return nil, fmt.Errorf("aes: unable to decode transformer key: %w", err) 100 } 101 if l := len(k); l != 64 { 102 return nil, fmt.Errorf("aes: invalid secret key length (%d)", l) 103 } 104 105 // Initialize AEAD 106 aead, err := miscreant.NewAEAD("AES-SIV", k, 16) 107 if err != nil { 108 return nil, fmt.Errorf("aes: unable to initialize aes-pmac-siv: %w", err) 109 } 110 111 // Return transformer 112 return &aeadTransformer{ 113 aead: aead, 114 }, nil 115 } 116 117 // AESPMACSIV returns an AES-PMAC-SIV value transformer instance. 118 func AESPMACSIV(key string) (value.Transformer, error) { 119 // Remove the prefix 120 key = strings.TrimPrefix(key, "aes-pmac-siv:") 121 122 // Decode key 123 k, err := base64.URLEncoding.DecodeString(key) 124 if err != nil { 125 return nil, fmt.Errorf("aes: unable to decode transformer key: %w", err) 126 } 127 if l := len(k); l != 64 { 128 return nil, fmt.Errorf("aes: invalid secret key length (%d)", l) 129 } 130 131 // Initialize AEAD 132 aead, err := miscreant.NewAEAD("AES-PMAC-SIV", k, 16) 133 if err != nil { 134 return nil, fmt.Errorf("aes: unable to initialize aes-pmac-siv: %w", err) 135 } 136 137 // Return transformer 138 return &aeadTransformer{ 139 aead: aead, 140 }, nil 141 } 142 143 // Chacha20Poly1305 returns an ChaCha20Poly1305 value transformer instance. 144 func Chacha20Poly1305(key string) (value.Transformer, error) { 145 // Remove the prefix 146 key = strings.TrimPrefix(key, "chacha:") 147 148 // Decode key 149 k, err := base64.URLEncoding.DecodeString(key) 150 if err != nil { 151 return nil, fmt.Errorf("chacha: unable to decode transformer key: %w", err) 152 } 153 if l := len(k); l != keyLength { 154 return nil, fmt.Errorf("chacha: invalid secret key length (%d)", l) 155 } 156 157 // Create Chacha20-Poly1305 aead cipher 158 aead, err := chacha20poly1305.New(k) 159 if err != nil { 160 return nil, fmt.Errorf("chacha: unable to initialize chacha cipher: %w", err) 161 } 162 163 // Return transformer 164 return &aeadTransformer{ 165 aead: aead, 166 }, nil 167 } 168 169 // XChacha20Poly1305 returns an XChaCha20Poly1305 value transformer instance. 170 func XChacha20Poly1305(key string) (value.Transformer, error) { 171 // Remove the prefix 172 key = strings.TrimPrefix(key, "xchacha:") 173 174 // Decode key 175 k, err := base64.URLEncoding.DecodeString(key) 176 if err != nil { 177 return nil, fmt.Errorf("xchacha: unable to decode transformer key: %w", err) 178 } 179 if l := len(k); l != keyLength { 180 return nil, fmt.Errorf("xchacha: invalid secret key length (%d)", l) 181 } 182 183 // Create Chacha20-Poly1305 aead cipher 184 aead, err := chacha20poly1305.NewX(k) 185 if err != nil { 186 return nil, fmt.Errorf("xchacha: unable to initialize chacha cipher: %w", err) 187 } 188 189 // Return transformer 190 return &aeadTransformer{ 191 aead: aead, 192 }, nil 193 }