// unwrapKey decrypts first key in keys whose encryption keys are in keycache func (encrypted *EncryptedData) unwrapKey(cache *keycache.Cache, user string) (unwrappedKey []byte, names []string, err error) { var ( keyFound error fullMatch bool = false nameSet = map[string]bool{} ) if len(encrypted.Predicate) == 0 { for _, mwKey := range encrypted.KeySet { // validate the size of the keys if len(mwKey.Key) != 16 { err = errors.New("Invalid Input") } if err != nil { return nil, nil, err } // loop through users to see if they are all delegated fullMatch = true for _, mwName := range mwKey.Name { if valid := cache.Valid(mwName, user, encrypted.Labels); !valid { fullMatch = false break } nameSet[mwName] = true } // if the keys are delegated, decrypt the mwKey with them if fullMatch == true { tmpKeyValue := mwKey.Key for _, mwName := range mwKey.Name { pubEncrypted := encrypted.KeySetRSA[mwName] if tmpKeyValue, keyFound = cache.DecryptKey(tmpKeyValue, mwName, user, encrypted.Labels, pubEncrypted.Key); keyFound != nil { break } } unwrappedKey = tmpKeyValue break } } if !fullMatch { err = errors.New("Need more delegated keys") names = nil } names = make([]string, 0, len(nameSet)) for name := range nameSet { names = append(names, name) } return } else { var sss msp.MSP sss, err = msp.StringToMSP(encrypted.Predicate) if err != nil { return nil, nil, err } db := msp.UserDatabase(UserDatabase{ names: &names, cache: cache, user: user, labels: encrypted.Labels, keySet: encrypted.KeySetRSA, shareSet: encrypted.ShareSet, }) unwrappedKey, err = sss.RecoverSecret(&db) return } }
// 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 }