github.com/zntrio/harp/v2@v2.0.9/pkg/sdk/value/encryption/dae/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 dae 19 20 import ( 21 "crypto/aes" 22 "crypto/cipher" 23 "crypto/sha256" 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 = "dae-aes-gcm" 38 aespmacsivPrefix = "dae-aes-pmac-siv" 39 aessivPrefix = "dae-aes-siv" 40 chachaPrefix = "dae-chacha" 41 xchachaPrefix = "dae-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, "dae-aes-gcm:") 59 60 k, salt, err := decodeKey(key) 61 if err != nil { 62 return nil, fmt.Errorf("aes: unable to decode transformer key: %w", err) 63 } 64 switch len(k) { 65 case 16, 24, 32: 66 default: 67 return nil, fmt.Errorf("aes: invalid key length, use 16 bytes (AES128) or 24 bytes (AES192) or 32 bytes (AES256)") 68 } 69 70 // Derive keys from input key 71 dk, err := deriveKey(k, salt, nil, len(k)+32) 72 if err != nil { 73 return nil, fmt.Errorf("aes: unable te derive required keys: %w", err) 74 } 75 76 // Create AES block cipher 77 block, err := aes.NewCipher(dk[:len(k)]) 78 if err != nil { 79 return nil, fmt.Errorf("aes: unable to initialize block cipher: %w", err) 80 } 81 82 // Initialize AEAD cipher chain 83 aead, err := cipher.NewGCM(block) 84 if err != nil { 85 return nil, fmt.Errorf("aes: unable to initialize aead chain : %w", err) 86 } 87 88 // Return transformer 89 return &daeTransformer{ 90 aead: aead, 91 nonceDeriverFunc: HMAC(sha256.New, dk[len(k):]), 92 }, nil 93 } 94 95 // AESSIV returns an AES-SIV/AES-CMAC-SIV value transformer instance. 96 func AESSIV(key string) (value.Transformer, error) { 97 // Remove the prefix 98 key = strings.TrimPrefix(key, "dae-aes-siv:") 99 100 // Decode key 101 k, salt, err := decodeKey(key) 102 if err != nil { 103 return nil, fmt.Errorf("aes: unable to decode transformer key: %w", err) 104 } 105 if l := len(k); l != 64 { 106 return nil, fmt.Errorf("aes: invalid secret key length (%d)", l) 107 } 108 109 // Derive keys from input key 110 dk, err := deriveKey(k, salt, nil, len(k)+32) 111 if err != nil { 112 return nil, fmt.Errorf("aes: unable te derive required keys: %w", err) 113 } 114 115 // Initialize AEAD 116 aead, err := miscreant.NewAEAD("AES-SIV", dk[:len(k)], 32) 117 if err != nil { 118 return nil, fmt.Errorf("aes: unable to initialize aes-pmac-siv: %w", err) 119 } 120 121 // Return transformer 122 return &daeTransformer{ 123 aead: aead, 124 nonceDeriverFunc: HMAC(sha256.New, dk[len(k):]), 125 }, nil 126 } 127 128 // AESPMACSIV returns an AES-PMAC-SIV value transformer instance. 129 func AESPMACSIV(key string) (value.Transformer, error) { 130 // Remove the prefix 131 key = strings.TrimPrefix(key, "dae-aes-pmac-siv:") 132 133 // Decode key 134 k, salt, err := decodeKey(key) 135 if err != nil { 136 return nil, fmt.Errorf("aes: unable to decode transformer key: %w", err) 137 } 138 if l := len(k); l != 64 { 139 return nil, fmt.Errorf("aes: invalid secret key length (%d)", l) 140 } 141 142 // Derive keys from input key 143 dk, err := deriveKey(k, salt, nil, len(k)+32) 144 if err != nil { 145 return nil, fmt.Errorf("aes: unable te derive required keys: %w", err) 146 } 147 148 // Initialize AEAD 149 aead, err := miscreant.NewAEAD("AES-PMAC-SIV", dk[:len(k)], 32) 150 if err != nil { 151 return nil, fmt.Errorf("aes: unable to initialize aes-pmac-siv: %w", err) 152 } 153 154 // Return transformer 155 return &daeTransformer{ 156 aead: aead, 157 nonceDeriverFunc: HMAC(sha256.New, dk[len(k):]), 158 }, nil 159 } 160 161 // Chacha20Poly1305 returns an ChaCha20Poly1305 value transformer instance. 162 func Chacha20Poly1305(key string) (value.Transformer, error) { 163 // Remove the prefix 164 key = strings.TrimPrefix(key, "dae-chacha:") 165 166 // Decode key 167 k, salt, err := decodeKey(key) 168 if err != nil { 169 return nil, fmt.Errorf("chacha: unable to decode transformer key: %w", err) 170 } 171 if l := len(k); l != 32 { 172 return nil, fmt.Errorf("chacha: invalid secret key length (%d)", l) 173 } 174 175 // Derive keys from input key 176 dk, err := deriveKey(k, salt, nil, len(k)+32) 177 if err != nil { 178 return nil, fmt.Errorf("chacha: unable te derive required keys: %w", err) 179 } 180 181 // Create Chacha20-Poly1305 aead cipher 182 aead, err := chacha20poly1305.New(dk[:len(k)]) 183 if err != nil { 184 return nil, fmt.Errorf("chacha: unable to initialize chacha cipher: %w", err) 185 } 186 187 // Return transformer 188 return &daeTransformer{ 189 aead: aead, 190 nonceDeriverFunc: HMAC(sha256.New, dk[len(k):]), 191 }, nil 192 } 193 194 // XChacha20Poly1305 returns an XChaCha20Poly1305 value transformer instance. 195 func XChacha20Poly1305(key string) (value.Transformer, error) { 196 // Remove the prefix 197 key = strings.TrimPrefix(key, "dae-xchacha:") 198 199 // Decode key 200 k, salt, err := decodeKey(key) 201 if err != nil { 202 return nil, fmt.Errorf("xchacha: unable to decode transformer key: %w", err) 203 } 204 if l := len(k); l != 32 { 205 return nil, fmt.Errorf("xchacha: invalid secret key length (%d)", l) 206 } 207 208 // Derive keys from input key 209 dk, err := deriveKey(k, salt, nil, len(k)+32) 210 if err != nil { 211 return nil, fmt.Errorf("xchacha: unable te derive required keys: %w", err) 212 } 213 214 // Create Chacha20-Poly1305 aead cipher 215 aead, err := chacha20poly1305.NewX(dk[:len(k)]) 216 if err != nil { 217 return nil, fmt.Errorf("xchacha: unable to initialize chacha cipher: %w", err) 218 } 219 220 // Return transformer 221 return &daeTransformer{ 222 aead: aead, 223 nonceDeriverFunc: HMAC(sha256.New, dk[len(k):]), 224 }, nil 225 }