private void readHeaderFields()

in src/main/java/com/amazonaws/encryptionsdk/internal/DecryptionHandler.java [574:679]


  private void readHeaderFields(final CiphertextHeaders ciphertextHeaders) {
    cryptoAlgo_ = ciphertextHeaders.getCryptoAlgoId();

    final CiphertextType ciphertextType = ciphertextHeaders.getType();
    if (ciphertextType != CiphertextType.CUSTOMER_AUTHENTICATED_ENCRYPTED_DATA) {
      throw new BadCiphertextException("Invalid type in ciphertext.");
    }

    final byte[] messageId = ciphertextHeaders.getMessageId();

    if (!commitmentPolicy_.algorithmAllowedForDecrypt(cryptoAlgo_)) {
      throw new AwsCryptoException(
          "Configuration conflict. "
              + "Cannot decrypt message with ID "
              + messageId
              + " due to CommitmentPolicy "
              + commitmentPolicy_
              + " requiring only committed messages. Algorithm ID was "
              + cryptoAlgo_
              + ". See: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/troubleshooting-migration.html");
    }

    if (maxEncryptedDataKeys_ > 0
        && ciphertextHeaders_.getEncryptedKeyBlobCount() > maxEncryptedDataKeys_) {
      throw new AwsCryptoException("Ciphertext encrypted data keys exceed maxEncryptedDataKeys");
    }

    if (!signaturePolicy_.algorithmAllowedForDecrypt(cryptoAlgo_)) {
      throw new AwsCryptoException(
          "Configuration conflict. "
              + "Cannot decrypt message with ID "
              + messageId
              + " because AwsCrypto.createUnsignedMessageDecryptingStream() "
              + " accepts only unsigned messages. Algorithm ID was "
              + cryptoAlgo_
              + ".");
    }

    encryptionContext_ = ciphertextHeaders.getEncryptionContextMap();

    DecryptionMaterialsRequest request =
        DecryptionMaterialsRequest.newBuilder()
            .setAlgorithm(cryptoAlgo_)
            .setEncryptionContext(encryptionContext_)
            .setEncryptedDataKeys(ciphertextHeaders.getEncryptedKeyBlobs())
            .build();

    DecryptionMaterials result = materialsManager_.decryptMaterials(request);

    //noinspection unchecked
    dataKey_ = (DataKey<K>) result.getDataKey();
    PublicKey trailingPublicKey = result.getTrailingSignatureKey();

    try {
      decryptionKey_ =
          cryptoAlgo_.getEncryptionKeyFromDataKey(dataKey_.getKey(), ciphertextHeaders);
    } catch (final InvalidKeyException ex) {
      throw new AwsCryptoException(ex);
    }

    if (cryptoAlgo_.getTrailingSignatureLength() > 0) {
      Utils.assertNonNull(trailingPublicKey, "trailing public key");

      TrailingSignatureAlgorithm trailingSignatureAlgorithm =
          TrailingSignatureAlgorithm.forCryptoAlgorithm(cryptoAlgo_);

      try {
        trailingSig_ = Signature.getInstance(trailingSignatureAlgorithm.getHashAndSignAlgorithm());

        trailingSig_.initVerify(trailingPublicKey);
      } catch (GeneralSecurityException e) {
        throw new AwsCryptoException(e);
      }
    } else {
      if (trailingPublicKey != null) {
        throw new AwsCryptoException("Unexpected trailing signature key in context");
      }

      trailingSig_ = null;
    }

    final ContentType contentType = ciphertextHeaders.getContentType();

    final short nonceLen = ciphertextHeaders.getNonceLength();
    final int frameLen = ciphertextHeaders.getFrameLength();

    verifyHeaderIntegrity(ciphertextHeaders);

    switch (contentType) {
      case FRAME:
        contentCryptoHandler_ =
            new FrameDecryptionHandler(
                decryptionKey_, (byte) nonceLen, cryptoAlgo_, messageId, frameLen);
        break;
      case SINGLEBLOCK:
        contentCryptoHandler_ =
            new BlockDecryptionHandler(decryptionKey_, (byte) nonceLen, cryptoAlgo_, messageId);
        break;
      default:
        // should never get here because an invalid content type is
        // detected when parsing.
        break;
    }

    ciphertextHeadersParsed_ = true;
  }