public void setFileCryptoMetaData()

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);
    }
  }