in parquet-hadoop/src/main/java/org/apache/parquet/crypto/InternalFileDecryptor.java [108:215]
public void setFileCryptoMetaData(
EncryptionAlgorithm algorithm, boolean encryptedFooter, byte[] footerKeyMetaData) {
// first use of the decryptor
if (!fileCryptoMetaDataProcessed) {
fileCryptoMetaDataProcessed = true;
this.encryptedFooter = encryptedFooter;
this.algorithm = algorithm;
this.footerKeyMetaData = footerKeyMetaData;
byte[] aadFileUnique;
boolean mustSupplyAadPrefix;
boolean fileHasAadPrefix = false;
byte[] aadPrefixInFile = null;
// Process encryption algorithm metadata
if (algorithm.isSetAES_GCM_V1()) {
if (algorithm.getAES_GCM_V1().isSetAad_prefix()) {
fileHasAadPrefix = true;
aadPrefixInFile = algorithm.getAES_GCM_V1().getAad_prefix();
}
mustSupplyAadPrefix = algorithm.getAES_GCM_V1().isSupply_aad_prefix();
aadFileUnique = algorithm.getAES_GCM_V1().getAad_file_unique();
} else if (algorithm.isSetAES_GCM_CTR_V1()) {
if (algorithm.getAES_GCM_CTR_V1().isSetAad_prefix()) {
fileHasAadPrefix = true;
aadPrefixInFile = algorithm.getAES_GCM_CTR_V1().getAad_prefix();
}
mustSupplyAadPrefix = algorithm.getAES_GCM_CTR_V1().isSupply_aad_prefix();
aadFileUnique = algorithm.getAES_GCM_CTR_V1().getAad_file_unique();
} else {
throw new ParquetCryptoRuntimeException("Unsupported algorithm: " + algorithm);
}
// Handle AAD prefix
byte[] aadPrefix = aadPrefixInProperties;
if (mustSupplyAadPrefix && (null == aadPrefixInProperties)) {
throw new ParquetCryptoRuntimeException("AAD prefix used for file encryption, "
+ "but not stored in file and not supplied in decryption properties");
}
if (fileHasAadPrefix) {
if (null != aadPrefixInProperties) {
if (!Arrays.equals(aadPrefixInProperties, aadPrefixInFile)) {
throw new ParquetCryptoRuntimeException(
"AAD Prefix in file and in decryption properties is not the same");
}
}
if (null != aadPrefixVerifier) {
aadPrefixVerifier.verify(aadPrefixInFile);
}
aadPrefix = aadPrefixInFile;
} else {
if (!mustSupplyAadPrefix && (null != aadPrefixInProperties)) {
throw new ParquetCryptoRuntimeException(
"AAD Prefix set in decryption properties, but was not used for file encryption");
}
if (null != aadPrefixVerifier) {
throw new ParquetCryptoRuntimeException(
"AAD Prefix Verifier is set, but AAD Prefix not found in file");
}
}
if (null == aadPrefix) {
this.fileAAD = aadFileUnique;
} else {
this.fileAAD = AesCipher.concatByteArrays(aadPrefix, aadFileUnique);
}
// Get footer key
if (null == footerKey) { // ignore footer key metadata if footer key is explicitly set via API
if (encryptedFooter || checkPlaintextFooterIntegrity) {
if (null == footerKeyMetaData) {
throw new ParquetCryptoRuntimeException("No footer key or key metadata");
}
if (null == keyRetriever) {
throw new ParquetCryptoRuntimeException("No footer key or key retriever");
}
try {
footerKey = keyRetriever.getKey(footerKeyMetaData);
} catch (KeyAccessDeniedException e) {
throw new KeyAccessDeniedException("Footer key: access denied", e);
}
if (null == footerKey) {
throw new ParquetCryptoRuntimeException("Footer key unavailable");
}
}
}
} else {
// re-use of the decryptor
// check the crypto metadata.
if (!this.algorithm.equals(algorithm)) {
throw new ParquetCryptoRuntimeException("Decryptor re-use: Different algorithm");
}
if (encryptedFooter != this.encryptedFooter) {
throw new ParquetCryptoRuntimeException("Decryptor re-use: Different footer encryption");
}
if (!Arrays.equals(this.footerKeyMetaData, footerKeyMetaData)) {
throw new ParquetCryptoRuntimeException("Decryptor re-use: Different footer key metadata");
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("File Decryptor. Algo: {}. Encrypted footer: {}", algorithm, encryptedFooter);
}
}