// encryptRSARecord takes an RSA private key and encrypts it with // a password key func encryptRSARecord(newRec *PasswordRecord, rsaPriv *rsa.PrivateKey, passKey []byte) (err error) { if newRec.RSAKey.RSAExpIV, err = makeRandom(16); err != nil { return } paddedExponent := padding.AddPadding(rsaPriv.D.Bytes()) if newRec.RSAKey.RSAExp, err = encryptCBC(paddedExponent, newRec.RSAKey.RSAExpIV, passKey); err != nil { return } if newRec.RSAKey.RSAPrimePIV, err = makeRandom(16); err != nil { return } paddedPrimeP := padding.AddPadding(rsaPriv.Primes[0].Bytes()) if newRec.RSAKey.RSAPrimeP, err = encryptCBC(paddedPrimeP, newRec.RSAKey.RSAPrimePIV, passKey); err != nil { return } if newRec.RSAKey.RSAPrimeQIV, err = makeRandom(16); err != nil { return } paddedPrimeQ := padding.AddPadding(rsaPriv.Primes[1].Bytes()) newRec.RSAKey.RSAPrimeQ, err = encryptCBC(paddedPrimeQ, newRec.RSAKey.RSAPrimeQIV, passKey) return }
// Encrypt secures and authenticates its input using the public key // using ECDHE with AES-128-CBC-HMAC-SHA1. func Encrypt(pub *ecdsa.PublicKey, in []byte) (out []byte, err error) { ephemeral, err := ecdsa.GenerateKey(Curve(), rand.Reader) if err != nil { return } x, _ := pub.Curve.ScalarMult(pub.X, pub.Y, ephemeral.D.Bytes()) if x == nil { return nil, errors.New("Failed to generate encryption key") } shared := sha256.Sum256(x.Bytes()) iv, err := symcrypt.MakeRandom(16) if err != nil { return } paddedIn := padding.AddPadding(in) ct, err := symcrypt.EncryptCBC(paddedIn, iv, shared[:16]) if err != nil { return } ephPub := elliptic.Marshal(pub.Curve, ephemeral.PublicKey.X, ephemeral.PublicKey.Y) out = make([]byte, 1+len(ephPub)+16) out[0] = byte(len(ephPub)) copy(out[1:], ephPub) copy(out[1+len(ephPub):], iv) out = append(out, ct...) h := hmac.New(sha1.New, shared[16:]) h.Write(iv) h.Write(ct) out = h.Sum(out) return }
func TestCrypt(t *testing.T) { msg := []byte("One ping only, please.") padMsg := padding.AddPadding(msg) key, err := MakeRandom(16) if err != nil { t.Fatalf("%v", err) } iv, err := MakeRandom(16) if err != nil { t.Fatalf("%v", err) } out, err := EncryptCBC(padMsg, iv, key) if err != nil { t.Fatalf("%v", err) } out, err = DecryptCBC(out, iv, key) if err != nil { t.Fatalf("%v", err) } unpadOut, err := padding.RemovePadding(out) if err != nil { t.Fatalf("%v", err) } else if !bytes.Equal(unpadOut, msg) { t.Fatal("Decrypted message doesn't match original plaintext.") } }
// encryptECCRecord takes an ECDSA private key and encrypts it with // a password key. func encryptECCRecord(newRec *PasswordRecord, ecPriv *ecdsa.PrivateKey, passKey []byte) (err error) { ecX509, err := x509.MarshalECPrivateKey(ecPriv) if err != nil { return } if newRec.ECKey.ECPrivIV, err = symcrypt.MakeRandom(16); err != nil { return } paddedX509 := padding.AddPadding(ecX509) newRec.ECKey.ECPriv, err = symcrypt.EncryptCBC(paddedX509, newRec.ECKey.ECPrivIV, passKey) return }
// Encrypt encrypts data with the keys associated with names. This // requires a minimum of min keys to decrypt. NOTE: as currently // implemented, the maximum value for min is 2. func (c *Cryptor) Encrypt(in []byte, labels []string, access AccessStructure) (resp []byte, err error) { var encrypted EncryptedData encrypted.Version = DEFAULT_VERSION if encrypted.VaultId, err = c.records.GetVaultID(); err != nil { return } // Generate random IV and encryption key encrypted.IV, err = symcrypt.MakeRandom(16) if err != nil { return } clearKey, err := symcrypt.MakeRandom(16) if err != nil { return } err = encrypted.wrapKey(c.records, clearKey, access) if err != nil { return } // encrypt file with clear key aesCrypt, err := aes.NewCipher(clearKey) if err != nil { return } clearFile := padding.AddPadding(in) encryptedFile := make([]byte, len(clearFile)) aesCBC := cipher.NewCBCEncrypter(aesCrypt, encrypted.IV) aesCBC.CryptBlocks(encryptedFile, clearFile) encrypted.Data = encryptedFile encrypted.Labels = labels hmacKey, err := c.records.GetHMACKey() if err != nil { return } encrypted.Signature = encrypted.computeHmac(hmacKey) encrypted.lock(hmacKey) return json.Marshal(encrypted) }
// Encrypt encrypts data with the keys associated with names. This // requires a minimum of min keys to decrypt. NOTE: as currently // implemented, the maximum value for min is 2. func Encrypt(in []byte, names []string, min int) (resp []byte, err error) { if min > 2 { return nil, errors.New("Minimum restricted to 2") } var encrypted EncryptedData encrypted.Version = DEFAULT_VERSION if encrypted.VaultId, err = passvault.GetVaultId(); err != nil { return } // Generate random IV and encryption key ivBytes, err := makeRandom(16) if err != nil { return } // append used here to make a new slice from ivBytes and assign to // encrypted.IV encrypted.IV = append([]byte{}, ivBytes...) clearKey, err := makeRandom(16) if err != nil { return } // Allocate set of keys to be able to cover all ordered subsets of // length 2 of names encrypted.KeySet = make([]MultiWrappedKey, len(names)*(len(names)-1)) encrypted.KeySetRSA = make(map[string]SingleWrappedKey) var singleWrappedKey SingleWrappedKey for _, name := range names { rec, ok := passvault.GetRecord(name) if !ok { err = errors.New("Missing user on disk") return } if rec.GetType() == passvault.RSARecord { // only wrap key with RSA key if found if singleWrappedKey.aesKey, err = makeRandom(16); err != nil { return nil, err } if singleWrappedKey.Key, err = rec.EncryptKey(singleWrappedKey.aesKey); err != nil { return nil, err } encrypted.KeySetRSA[name] = singleWrappedKey } else { err = nil } } // encrypt file key with every combination of two keys var n int for _, nameOuter := range names { for _, nameInner := range names { if nameInner != nameOuter { encrypted.KeySet[n], err = encryptKey(nameInner, nameOuter, clearKey, encrypted.KeySetRSA) n += 1 } if err != nil { return } } } // encrypt file with clear key aesCrypt, err := aes.NewCipher(clearKey) if err != nil { return } clearFile := padding.AddPadding(in) encryptedFile := make([]byte, len(clearFile)) aesCBC := cipher.NewCBCEncrypter(aesCrypt, ivBytes) aesCBC.CryptBlocks(encryptedFile, clearFile) encrypted.Data = encryptedFile hmacKey, err := passvault.GetHmacKey() if err != nil { return } encrypted.Signature = computeHmac(hmacKey, encrypted) return json.Marshal(encrypted) }