github.com/opendevstack/tailor@v1.3.5-0.20220119161809-cab064e60a67/pkg/utils/encryption.go (about) 1 package utils 2 3 import ( 4 "bytes" 5 "crypto" 6 "encoding/base64" 7 "fmt" 8 "io" 9 "io/ioutil" 10 "os" 11 12 "golang.org/x/crypto/openpgp" 13 "golang.org/x/crypto/openpgp/armor" 14 "golang.org/x/crypto/openpgp/packet" 15 ) 16 17 func CreateEntity(name, email string) (*openpgp.Entity, error) { 18 var e *openpgp.Entity 19 conf := &packet.Config{ 20 RSABits: 4096, 21 DefaultHash: crypto.SHA256, 22 DefaultCipher: packet.CipherFunction(packet.CipherAES128), 23 } 24 e, err := openpgp.NewEntity(name, "Generated by tailor", email, conf) 25 if err != nil { 26 return nil, err 27 } 28 29 // Sign all the identities 30 for _, id := range e.Identities { 31 err := id.SelfSignature.SignUserId(id.UserId.Id, e.PrimaryKey, e.PrivateKey, nil) 32 if err != nil { 33 return nil, err 34 } 35 } 36 return e, nil 37 } 38 39 func PrintPublicKey(entity *openpgp.Entity, filename string) error { 40 f, err := os.Create(filename) 41 if err != nil { 42 return err 43 } 44 w, err := armor.Encode(f, openpgp.PublicKeyType, nil) 45 if err != nil { 46 return err 47 } 48 defer w.Close() 49 err = entity.Serialize(w) 50 if err != nil { 51 return err 52 } 53 _, err = io.WriteString(f, "\n") 54 if err != nil { 55 return err 56 } 57 return nil 58 } 59 60 func PrintPrivateKey(entity *openpgp.Entity, filename string) error { 61 f, err := os.Create(filename) 62 if err != nil { 63 return err 64 } 65 w, err := armor.Encode(f, openpgp.PrivateKeyType, nil) 66 if err != nil { 67 return err 68 } 69 err = entity.SerializePrivate(w, nil) 70 if err != nil { 71 return err 72 } 73 w.Close() 74 _, err = io.WriteString(f, "\n") 75 if err != nil { 76 return err 77 } 78 return nil 79 } 80 81 // Assembles entity list from keys in given files 82 func GetEntityList(keys []string, passphrase string) (openpgp.EntityList, error) { 83 entityList := openpgp.EntityList{} 84 for _, filename := range keys { 85 keyringFileBuffer, _ := os.Open(filename) 86 defer keyringFileBuffer.Close() 87 l, err := openpgp.ReadArmoredKeyRing(keyringFileBuffer) 88 if err != nil { 89 return entityList, fmt.Errorf( 90 "Reading key '%s' failed: %s", 91 filename, 92 err, 93 ) 94 } 95 entity := l[0] 96 97 // Decrypt private key using passphrase 98 passphraseBytes := []byte(passphrase) 99 if entity.PrivateKey != nil && entity.PrivateKey.Encrypted { 100 err := entity.PrivateKey.Decrypt(passphraseBytes) 101 if err != nil { 102 return entityList, fmt.Errorf("Failed to decrypt key: %s", err) 103 } 104 } 105 for _, subkey := range entity.Subkeys { 106 if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted { 107 err := subkey.PrivateKey.Decrypt(passphraseBytes) 108 if err != nil { 109 return entityList, fmt.Errorf( 110 "Failed to decrypt subkey: %s", err, 111 ) 112 } 113 } 114 } 115 116 entityList = append(entityList, entity) 117 } 118 return entityList, nil 119 } 120 121 // Encrypts secret with all public keys and base64-encodes the result. 122 func Encrypt(secret string, entityList openpgp.EntityList) (string, error) { 123 // Encrypt message using public keys 124 buf := new(bytes.Buffer) 125 w, err := openpgp.Encrypt(buf, entityList, nil, nil, nil) 126 if err != nil { 127 return "", fmt.Errorf("Encrypting '%s' failed: %s", secret, err) 128 } 129 _, err = w.Write([]byte(secret)) 130 if err != nil { 131 return "", err 132 } 133 err = w.Close() 134 if err != nil { 135 return "", err 136 } 137 138 // Return as base64 encoded string 139 bytes, err := ioutil.ReadAll(buf) 140 if err != nil { 141 return "", err 142 } 143 str := base64.StdEncoding.EncodeToString(bytes) 144 return str, nil 145 } 146 147 // Decrypts the base64-encoded string end decrypts with the private key. 148 func Decrypt(encoded string, entityList openpgp.EntityList) (string, error) { 149 // Decode bas64-encoded string 150 encrypted, err := base64.StdEncoding.DecodeString(encoded) 151 if err != nil { 152 return "", fmt.Errorf("Decoding '%s' failed: %s", encoded, err) 153 } 154 155 // Decrypt encrypted message 156 buf := bytes.NewBuffer([]byte(encrypted)) 157 md, err := openpgp.ReadMessage(buf, entityList, nil, nil) 158 if err != nil { 159 return "", fmt.Errorf("Decrypting '%s' failed: %s", encoded, err) 160 } 161 bytes, err := ioutil.ReadAll(md.UnverifiedBody) 162 return string(bytes), err 163 }