in client/client.go [605:680]
func (c *StetClient) Decrypt(ctx context.Context, input io.Reader, output io.Writer, stetConfig *configpb.StetConfig) (*StetMetadata, error) {
config := stetConfig.GetDecryptConfig()
if config == nil {
return nil, fmt.Errorf("nil DecryptConfig passed to Decrypt()")
}
metadata, err := ReadMetadata(input)
if err != nil {
return nil, fmt.Errorf("error reading metadata: %v", err)
}
// Find matching KeyConfig.
var matchingKeyConfig *configpb.KeyConfig
for _, keyCfg := range config.GetKeyConfigs() {
if proto.Equal(keyCfg, metadata.GetKeyConfig()) {
matchingKeyConfig = keyCfg
break
}
}
if matchingKeyConfig == nil {
return nil, fmt.Errorf("no known KeyConfig matches given data")
}
// Unwrap shares and validate.
opts := sharesOpts{
kekInfos: matchingKeyConfig.GetKekInfos(),
asymmetricKeys: stetConfig.GetAsymmetricKeys(),
confSpaceConfig: c.newConfSpaceConfig(stetConfig),
}
unwrappedShares, err := c.unwrapAndValidateShares(ctx, metadata.GetShares(), opts)
if err != nil {
return nil, fmt.Errorf("error unwrapping and validating shares: %v", err)
}
// Verify we have enough unwrapped shares for the key config.
if err := enoughUnwrappedShares(unwrappedShares, matchingKeyConfig); err != nil {
return nil, fmt.Errorf("not enough unwrapped shares to recombine DEK, see logs for unwrap details: %v", err)
} else if len(unwrappedShares) < len(matchingKeyConfig.GetKekInfos()) {
glog.Warningf("Recieved enough unwrapped shares to recombine DEK, but not all shares unwrapped successfully: %v of %v unwrapped, see logs for unwrap details.", len(unwrappedShares), len(matchingKeyConfig.GetKekInfos()))
}
combinedShares, err := shares.CombineUnwrappedShares(matchingKeyConfig, unwrappedShares)
if err != nil {
return nil, fmt.Errorf("error combining unwrapped shares: %v", err)
}
var combinedDEK shares.DEK
copy(combinedDEK[:], combinedShares)
// Generate AAD and decrypt ciphertext.
aad, err := MetadataToAAD(metadata)
if err != nil {
return nil, fmt.Errorf("error serializing metadata: %v", err)
}
// Now `input` is at the start of ciphertext to pass to Tink.
if err := AeadDecrypt(combinedDEK, input, output, aad); err != nil {
return nil, fmt.Errorf("error decrypting data: %v", err)
}
// Return URIs of keys used during decryption.
var keyURIs []string
for _, unwrapped := range unwrappedShares {
if unwrapped.URI != "" {
keyURIs = append(keyURIs, unwrapped.URI)
}
}
return &StetMetadata{
KeyUris: keyURIs,
BlobID: metadata.GetBlobId(),
}, nil
}