// createPasswordRec creates a new record from a username and password func createPasswordRec(password string, admin bool) (newRec PasswordRecord, err error) { newRec.Type = DefaultRecordType if newRec.PasswordSalt, err = symcrypt.MakeRandom(16); err != nil { return } if newRec.HashedPassword, err = hashPassword(password, newRec.PasswordSalt); err != nil { return } if newRec.KeySalt, err = symcrypt.MakeRandom(16); err != nil { return } passKey, err := derivePasswordKey(password, newRec.KeySalt) if err != nil { return } // generate a key pair switch DefaultRecordType { case RSARecord: var rsaPriv *rsa.PrivateKey rsaPriv, err = rsa.GenerateKey(rand.Reader, 2048) if err != nil { return } // encrypt RSA key with password key if err = encryptRSARecord(&newRec, rsaPriv, passKey); err != nil { return } newRec.RSAKey.RSAPublic = rsaPriv.PublicKey case ECCRecord: var ecPriv *ecdsa.PrivateKey ecPriv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { return } // encrypt ECDSA key with password key if err = encryptECCRecord(&newRec, ecPriv, passKey); err != nil { return } newRec.ECKey.ECPublic = ecPriv.PublicKey } // encrypt AES key with password key aesKey, err := symcrypt.MakeRandom(16) if err != nil { return } if newRec.AESKey, err = encryptECB(aesKey, passKey); err != nil { return } newRec.Admin = admin return }
// 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 = symcrypt.MakeRandom(16); err != nil { return } paddedExponent := padding.AddPadding(rsaPriv.D.Bytes()) if newRec.RSAKey.RSAExp, err = symcrypt.EncryptCBC(paddedExponent, newRec.RSAKey.RSAExpIV, passKey); err != nil { return } if newRec.RSAKey.RSAPrimePIV, err = symcrypt.MakeRandom(16); err != nil { return } paddedPrimeP := padding.AddPadding(rsaPriv.Primes[0].Bytes()) if newRec.RSAKey.RSAPrimeP, err = symcrypt.EncryptCBC(paddedPrimeP, newRec.RSAKey.RSAPrimePIV, passKey); err != nil { return } if newRec.RSAKey.RSAPrimeQIV, err = symcrypt.MakeRandom(16); err != nil { return } paddedPrimeQ := padding.AddPadding(rsaPriv.Primes[1].Bytes()) newRec.RSAKey.RSAPrimeQ, err = symcrypt.EncryptCBC(paddedPrimeQ, newRec.RSAKey.RSAPrimeQIV, passKey) return }
// ChangePassword changes the password for a given user. func (records *Records) ChangePassword(name, password, newPassword string) (err error) { pr, ok := records.GetRecord(name) if !ok { err = errors.New("Record not present") return } var keySalt []byte if keySalt, err = symcrypt.MakeRandom(16); err != nil { return } newPassKey, err := derivePasswordKey(newPassword, keySalt) if err != nil { return } // decrypt with old password and re-encrypt original key with new password if pr.Type == RSARecord { var rsaKey rsa.PrivateKey rsaKey, err = pr.GetKeyRSA(password) if err != nil { return } // encrypt RSA key with password key err = encryptRSARecord(&pr, &rsaKey, newPassKey) if err != nil { return } } else if pr.Type == ECCRecord { var ecKey *ecdsa.PrivateKey ecKey, err = pr.GetKeyECC(password) if err != nil { return } // encrypt ECDSA key with password key err = encryptECCRecord(&pr, ecKey, newPassKey) if err != nil { return } } else { err = errors.New("Unkown record type") return } // add the password salt and hash if pr.PasswordSalt, err = symcrypt.MakeRandom(16); err != nil { return } if pr.HashedPassword, err = hashPassword(newPassword, pr.PasswordSalt); err != nil { return } pr.KeySalt = keySalt records.SetRecord(pr, name) return records.WriteRecordsToDisk() }
// createPasswordRec creates a new record from a username and password func createPasswordRec(password string, admin bool, userType string) (newRec PasswordRecord, err error) { newRec.Type = userType if newRec.PasswordSalt, err = symcrypt.MakeRandom(16); err != nil { return } if newRec.HashedPassword, err = hashPassword(password, newRec.PasswordSalt); err != nil { return } if newRec.KeySalt, err = symcrypt.MakeRandom(16); err != nil { return } passKey, err := derivePasswordKey(password, newRec.KeySalt) if err != nil { return } newRec.AltNames = make(map[string]string) // generate a key pair switch userType { case RSARecord: var rsaPriv *rsa.PrivateKey rsaPriv, err = rsa.GenerateKey(rand.Reader, 2048) if err != nil { return } // encrypt RSA key with password key if err = encryptRSARecord(&newRec, rsaPriv, passKey); err != nil { return } newRec.RSAKey.RSAPublic = rsaPriv.PublicKey case ECCRecord: var ecPriv *ecdsa.PrivateKey ecPriv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { return } // encrypt ECDSA key with password key if err = encryptECCRecord(&newRec, ecPriv, passKey); err != nil { return } newRec.ECKey.ECPublic.Curve = ecPriv.PublicKey.Curve.Params() newRec.ECKey.ECPublic.X = ecPriv.PublicKey.X newRec.ECKey.ECPublic.Y = ecPriv.PublicKey.Y default: err = errors.New("Unknown record type") } newRec.Admin = admin return }
func init() { // seed math.random from crypto.random seedBytes, _ := symcrypt.MakeRandom(8) seedBuf := bytes.NewBuffer(seedBytes) n64, _ := binary.ReadVarint(seedBuf) mrand.Seed(n64) }
// 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 }
// 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) }
// 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 }
// ChangePassword changes the password for a given user. func ChangePassword(name, password, newPassword string) (err error) { pr, ok := GetRecord(name) if !ok { err = errors.New("Record not present") return } if err = pr.ValidatePassword(password); err != nil { return } // decrypt key var key []byte var rsaKey rsa.PrivateKey var ecKey *ecdsa.PrivateKey if pr.Type == AESRecord { key, err = pr.GetKeyAES(password) if err != nil { return } } else if pr.Type == RSARecord { rsaKey, err = pr.GetKeyRSA(password) if err != nil { return } } else if pr.Type == ECCRecord { ecKey, err = pr.GetKeyECC(password) if err != nil { return } } else { err = errors.New("Unkown record type") return } // add the password salt and hash if pr.PasswordSalt, err = symcrypt.MakeRandom(16); err != nil { return } if pr.HashedPassword, err = hashPassword(newPassword, pr.PasswordSalt); err != nil { return } if pr.KeySalt, err = symcrypt.MakeRandom(16); err != nil { return } newPassKey, err := derivePasswordKey(newPassword, pr.KeySalt) if err != nil { return } // encrypt original key with new password if pr.Type == AESRecord { pr.AESKey, err = encryptECB(key, newPassKey) if err != nil { return } } else if pr.Type == RSARecord { // encrypt RSA key with password key err = encryptRSARecord(&pr, &rsaKey, newPassKey) if err != nil { return } } else if pr.Type == ECCRecord { // encrypt ECDSA key with password key err = encryptECCRecord(&pr, ecKey, newPassKey) if err != nil { return } } else { err = errors.New("Unkown record type") return } SetRecord(pr, name) return WriteRecordsToDisk() }
// InitFromDisk reads the record from disk and initialize global context. func InitFromDisk(path string) error { jsonDiskRecord, err := ioutil.ReadFile(path) // It's OK for the file to be missing, we'll create it later if // anything is added. if err != nil && !os.IsNotExist(err) { return err } // Initialized so that we can determine later if anything was read // from the file. records.Version = 0 if len(jsonDiskRecord) != 0 { if err = json.Unmarshal(jsonDiskRecord, &records); err != nil { return err } } formatErr := errors.New("Format error") for _, rec := range records.Passwords { if len(rec.PasswordSalt) != 16 { return formatErr } if len(rec.HashedPassword) != 16 { return formatErr } if len(rec.KeySalt) != 16 { return formatErr } if rec.Type == AESRecord { if len(rec.AESKey) != 16 { return formatErr } } if rec.Type == RSARecord { if len(rec.RSAKey.RSAExp) == 0 || len(rec.RSAKey.RSAExp)%16 != 0 { return formatErr } if len(rec.RSAKey.RSAPrimeP) == 0 || len(rec.RSAKey.RSAPrimeP)%16 != 0 { return formatErr } if len(rec.RSAKey.RSAPrimeQ) == 0 || len(rec.RSAKey.RSAPrimeQ)%16 != 0 { return formatErr } if len(rec.RSAKey.RSAExpIV) != 16 { return formatErr } if len(rec.RSAKey.RSAPrimePIV) != 16 { return formatErr } if len(rec.RSAKey.RSAPrimeQIV) != 16 { return formatErr } } if rec.Type == ECCRecord { if len(rec.ECKey.ECPriv) == 0 { return formatErr } } } // If the Version field is 0 then it indicates that nothing was // read from the file and so it needs to be initialized. if records.Version == 0 { records.Version = DEFAULT_VERSION records.VaultId = int(mrand.Int31()) records.HmacKey, err = symcrypt.MakeRandom(16) if err != nil { return err } records.Passwords = make(map[string]PasswordRecord) } localPath = path return nil }
func TestUsesFlush(t *testing.T) { // Initialize passvault with one dummy user. records, err := passvault.InitFrom("memory") if err != nil { t.Fatalf("%v", err) } pr, err := records.AddNewRecord("user", "weakpassword", true, passvault.DefaultRecordType) if err != nil { t.Fatalf("%v", err) } // Initialize keycache and delegate the user's key to it. cache := NewCache() err = cache.AddKeyFromRecord(pr, "user", "weakpassword", nil, nil, 2, "", "1h") if err != nil { t.Fatalf("%v", err) } cache.Refresh() if len(cache.UserKeys) != 1 { t.Fatalf("Error in number of live keys") } // Generate a random symmetric key, encrypt a blank block with it, and encrypt // the key itself with the user's public key. dummy := make([]byte, 16) key, err := symcrypt.MakeRandom(16) if err != nil { t.Fatalf("%v", err) } encKey, err := symcrypt.EncryptCBC(dummy, dummy, key) if err != nil { t.Fatalf("%v", err) } pubEncryptedKey, err := pr.EncryptKey(key) if err != nil { t.Fatalf("%v", err) } key2, err := cache.DecryptKey(encKey, "user", "anybody", []string{}, pubEncryptedKey) if err != nil { t.Fatalf("%v", err) } if bytes.Equal(key, key2) { t.Fatalf("cache.DecryptKey didnt decrypt the right key!") } // Second decryption allowed. _, err = cache.DecryptKey(encKey, "user", "anybody else", []string{}, pubEncryptedKey) if err != nil { t.Fatalf("%v", err) } if len(cache.UserKeys) != 0 { t.Fatalf("Error in number of live keys %v", cache.UserKeys) } }
// wrapKey encrypts the clear key according to an access structure. func (encrypted *EncryptedData) wrapKey(records *passvault.Records, clearKey []byte, access AccessStructure) (err error) { generateRandomKey := func(name string) (singleWrappedKey SingleWrappedKey, err error) { rec, ok := records.GetRecord(name) if !ok { err = errors.New("Missing user on disk") return } if singleWrappedKey.aesKey, err = symcrypt.MakeRandom(16); err != nil { return } if singleWrappedKey.Key, err = rec.EncryptKey(singleWrappedKey.aesKey); err != nil { return } return } encryptKey := func(outer, inner string, clearKey []byte) (keyBytes []byte, err error) { var outerCrypt, innerCrypt cipher.Block keyBytes = make([]byte, 16) outerCrypt, err = aes.NewCipher(encrypted.KeySetRSA[outer].aesKey) if err != nil { return } innerCrypt, err = aes.NewCipher(encrypted.KeySetRSA[inner].aesKey) if err != nil { return } innerCrypt.Encrypt(keyBytes, clearKey) outerCrypt.Encrypt(keyBytes, keyBytes) return } if len(access.Names) > 0 { // Generate a random AES key for each user and RSA/ECIES encrypt it encrypted.KeySetRSA = make(map[string]SingleWrappedKey) for _, name := range access.Names { encrypted.KeySetRSA[name], err = generateRandomKey(name) if err != nil { return err } } // encrypt file key with every combination of two keys encrypted.KeySet = make([]MultiWrappedKey, 0) for i := 0; i < len(access.Names); i++ { for j := i + 1; j < len(access.Names); j++ { keyBytes, err := encryptKey(access.Names[i], access.Names[j], clearKey) if err != nil { return err } out := MultiWrappedKey{ Name: []string{access.Names[i], access.Names[j]}, Key: keyBytes, } encrypted.KeySet = append(encrypted.KeySet, out) } } } else if len(access.LeftNames) > 0 && len(access.RightNames) > 0 { // Generate a random AES key for each user and RSA/ECIES encrypt it encrypted.KeySetRSA = make(map[string]SingleWrappedKey) for _, name := range access.LeftNames { encrypted.KeySetRSA[name], err = generateRandomKey(name) if err != nil { return err } } for _, name := range access.RightNames { encrypted.KeySetRSA[name], err = generateRandomKey(name) if err != nil { return err } } // encrypt file key with every combination of one left key and one right key encrypted.KeySet = make([]MultiWrappedKey, 0) for _, leftName := range access.LeftNames { for _, rightName := range access.RightNames { if leftName == rightName { continue } keyBytes, err := encryptKey(leftName, rightName, clearKey) if err != nil { return err } out := MultiWrappedKey{ Name: []string{leftName, rightName}, Key: keyBytes, } encrypted.KeySet = append(encrypted.KeySet, out) } } } else if len(access.Predicate) > 0 { encrypted.KeySetRSA = make(map[string]SingleWrappedKey) sss, err := msp.StringToMSP(access.Predicate) if err != nil { return err } db := msp.UserDatabase(UserDatabase{records: records}) shareSet, err := sss.DistributeShares(clearKey, &db) if err != nil { return err } for name, _ := range shareSet { encrypted.KeySetRSA[name], err = generateRandomKey(name) if err != nil { return err } crypt, err := aes.NewCipher(encrypted.KeySetRSA[name].aesKey) if err != nil { return err } for i, _ := range shareSet[name] { tmp := make([]byte, 16) crypt.Encrypt(tmp, shareSet[name][i]) shareSet[name][i] = tmp } } encrypted.ShareSet = shareSet encrypted.Predicate = access.Predicate } else { return errors.New("Invalid access structure.") } return nil }
// 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 := symcrypt.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 := symcrypt.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 || rec.GetType() == passvault.ECCRecord { // only wrap key with RSA key if found if singleWrappedKey.aesKey, err = symcrypt.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) }