private void actualEncryption()

in DynamoDbEncryption/runtimes/java/src/main/sdkv1/com/amazonaws/services/dynamodbv2/datamodeling/encryption/DynamoDBEncryptor.java [544:614]


  private void actualEncryption(
    Map<String, AttributeValue> itemAttributes,
    Map<String, Set<EncryptionFlags>> attributeActionsOnEncrypt,
    Map<String, String> materialDescription,
    SecretKey encryptionKey
  ) throws GeneralSecurityException {
    String encryptionMode = null;
    if (encryptionKey != null) {
      materialDescription.put(
        this.symmetricEncryptionModeHeader,
        SYMMETRIC_ENCRYPTION_MODE
      );
      encryptionMode = encryptionKey.getAlgorithm() + SYMMETRIC_ENCRYPTION_MODE;
    }
    Cipher cipher = null;
    int blockSize = -1;

    for (Map.Entry<String, AttributeValue> entry : itemAttributes.entrySet()) {
      Set<EncryptionFlags> flags = attributeActionsOnEncrypt.get(
        entry.getKey()
      );
      if (flags != null && flags.contains(EncryptionFlags.ENCRYPT)) {
        if (!flags.contains(EncryptionFlags.SIGN)) {
          throw new IllegalArgumentException(
            "All encrypted fields must be signed. Bad field: " + entry.getKey()
          );
        }
        ByteBuffer plainText = AttributeValueMarshaller.marshall(
          entry.getValue()
        );
        plainText.rewind();
        ByteBuffer cipherText;
        if (encryptionKey instanceof DelegatedKey) {
          DelegatedKey dk = (DelegatedKey) encryptionKey;
          cipherText =
            ByteBuffer.wrap(
              dk.encrypt(toByteArray(plainText), null, encryptionMode)
            );
        } else {
          if (cipher == null) {
            blockSize = getBlockSize(encryptionMode);
            cipher = Cipher.getInstance(encryptionMode);
          }
          // Encryption format: <iv><ciphertext>
          // Note a unique iv is generated per attribute
          cipher.init(Cipher.ENCRYPT_MODE, encryptionKey, Utils.getRng());
          cipherText =
            ByteBuffer.allocate(
              blockSize + cipher.getOutputSize(plainText.remaining())
            );
          cipherText.position(blockSize);
          cipher.doFinal(plainText, cipherText);
          cipherText.flip();
          final byte[] iv = cipher.getIV();
          if (iv.length != blockSize) {
            throw new IllegalStateException(
              String.format(
                "Generated IV length (%d) not equal to block size (%d)",
                iv.length,
                blockSize
              )
            );
          }
          cipherText.put(iv);
          cipherText.rewind();
        }
        // Replace the plaintext attribute value with the encrypted content
        entry.setValue(new AttributeValue().withB(cipherText));
      }
    }
  }