Example #1
0
// 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
	}
}
Example #2
0
// 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
}