github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/encrypt/aesgcm.go (about) 1 // Copyright 2023 The GitBundle Inc. All rights reserved. 2 // Copyright 2017 The Gitea Authors. All rights reserved. 3 // Use of this source code is governed by a MIT-style 4 // license that can be found in the LICENSE file. 5 6 // Copyright 2019 Drone IO, Inc. 7 // 8 // Licensed under the Apache License, Version 2.0 (the "License"); 9 // you may not use this file except in compliance with the License. 10 // You may obtain a copy of the License at 11 // 12 // http://www.apache.org/licenses/LICENSE-2.0 13 // 14 // Unless required by applicable law or agreed to in writing, software 15 // distributed under the License is distributed on an "AS IS" BASIS, 16 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 // See the License for the specific language governing permissions and 18 // limitations under the License. 19 20 package encrypt 21 22 import ( 23 "crypto/aes" 24 "crypto/cipher" 25 "crypto/rand" 26 "errors" 27 "io" 28 ) 29 30 // Aesgcm provides an encrypter that uses the aesgcm encryption 31 // algorithm. 32 type Aesgcm struct { 33 block cipher.Block 34 Compat bool 35 } 36 37 // Encrypt encrypts the plaintext using aesgcm. 38 func (e *Aesgcm) Encrypt(plaintext string) ([]byte, error) { 39 gcm, err := cipher.NewGCM(e.block) 40 if err != nil { 41 return nil, err 42 } 43 44 nonce := make([]byte, gcm.NonceSize()) 45 _, err = io.ReadFull(rand.Reader, nonce) 46 if err != nil { 47 return nil, err 48 } 49 50 return gcm.Seal(nonce, nonce, []byte(plaintext), nil), nil 51 } 52 53 // Decrypt decrypts the ciphertext using aesgcm. 54 func (e *Aesgcm) Decrypt(ciphertext []byte) (string, error) { 55 gcm, err := cipher.NewGCM(e.block) 56 if err != nil { 57 return "", err 58 } 59 60 if len(ciphertext) < gcm.NonceSize() { 61 // if the decryption utility is running in compatibility 62 // mode, it will return the ciphertext as plain text if 63 // decryption fails. This should be used when running the 64 // database in mixed-mode, where there is a mix of encrypted 65 // and unencrypted content. 66 if e.Compat { 67 return string(ciphertext), nil 68 } 69 return "", errors.New("malformed ciphertext") 70 } 71 72 plaintext, err := gcm.Open(nil, 73 ciphertext[:gcm.NonceSize()], 74 ciphertext[gcm.NonceSize():], 75 nil, 76 ) 77 // if the decryption utility is running in compatibility 78 // mode, it will return the ciphertext as plain text if 79 // decryption fails. This should be used when running the 80 // database in mixed-mode, where there is a mix of encrypted 81 // and unencrypted content. 82 if err != nil && e.Compat { 83 return string(ciphertext), nil 84 } 85 return string(plaintext), err 86 } 87 88 func AesGcmKey32Encrypt(key, plaintext []byte) ([]byte, error) { 89 if len(key) != 32 { 90 return nil, errKeySize 91 } 92 return AesGcmEncrypt(key, plaintext) 93 } 94 95 func AesGcmKey32Decrypt(key, ciphertext []byte) ([]byte, error) { 96 if len(key) != 32 { 97 return nil, errKeySize 98 } 99 return AesGcmDecrypt(key, ciphertext) 100 } 101 102 // AesGcmEncrypt (from legacy package): encrypts plaintext with the given key using AES in GCM mode. should be replaced. 103 func AesGcmEncrypt(key, plaintext []byte) ([]byte, error) { 104 block, err := aes.NewCipher(key) 105 if err != nil { 106 return nil, err 107 } 108 109 gcm, err := cipher.NewGCM(block) 110 if err != nil { 111 return nil, err 112 } 113 114 nonce := make([]byte, gcm.NonceSize()) 115 _, err = io.ReadFull(rand.Reader, nonce) 116 if err != nil { 117 return nil, err 118 } 119 120 return gcm.Seal(nonce, nonce, []byte(plaintext), nil), nil 121 } 122 123 // AesGcmDecrypt (from legacy package): decrypts ciphertext with the given key using AES in GCM mode. should be replaced. 124 func AesGcmDecrypt(key, ciphertext []byte) ([]byte, error) { 125 block, err := aes.NewCipher(key) 126 if err != nil { 127 return nil, err 128 } 129 130 gcm, err := cipher.NewGCM(block) 131 if err != nil { 132 return nil, err 133 } 134 135 if len(ciphertext) < gcm.NonceSize() { 136 return nil, errors.New("malformed ciphertext") 137 } 138 139 plainText, err := gcm.Open(nil, 140 ciphertext[:gcm.NonceSize()], 141 ciphertext[gcm.NonceSize():], 142 nil, 143 ) 144 if err != nil { 145 return nil, err 146 } 147 148 return plainText, nil 149 }