@Before public void setUp() { dynamoDBClient = Mockito.mock(AmazonDynamoDB.class); GenerateDataKeyResult generateDatakeyResult = new GenerateDataKeyResult(); generateDatakeyResult.setCiphertextBlob(Mockito.mock(ByteBuffer.class)); generateDatakeyResult.setPlaintext(Mockito.mock(ByteBuffer.class)); DecryptResult decryptResult = new DecryptResult(); decryptResult.setKeyId("alias/foo"); decryptResult.setPlaintext(Mockito.mock(ByteBuffer.class)); awskmsClient = Mockito.mock(AWSKMS.class); Mockito.when(awskmsClient.generateDataKey(Mockito.any(GenerateDataKeyRequest.class))).thenReturn(generateDatakeyResult); Mockito.when(awskmsClient.decrypt(Mockito.any(DecryptRequest.class))).thenReturn(decryptResult); }
@Override public DecryptResult decrypt(DecryptRequest req) throws AmazonServiceException, AmazonClientException { DecryptResult result = results_.get(new DecryptMapKey(req)); if (result != null) { // Copy it to avoid external modification DecryptResult copy = new DecryptResult(); copy.setKeyId(retrieveArn(result.getKeyId())); byte[] pt = new byte[result.getPlaintext().limit()]; result.getPlaintext().get(pt); result.getPlaintext().rewind(); copy.setPlaintext(ByteBuffer.wrap(pt)); return copy; } else { throw new InvalidCiphertextException("Invalid Ciphertext"); } }
public static String decrypt(String str, Region region) throws UnsupportedEncodingException { if (isJUnitTest()) { return str; } AWSKMS kms = AWSKMSClientBuilder.standard().withRegion(region.getName()).build(); /* * The KMS ciphertext is base64 encoded and must be decoded before the request is made */ String cipherString = str; byte[] cipherBytes = Base64.decode(cipherString); /* * Create decode request and decode */ ByteBuffer cipherBuffer = ByteBuffer.wrap(cipherBytes); DecryptRequest req = new DecryptRequest().withCiphertextBlob(cipherBuffer); DecryptResult resp = kms.decrypt(req); /* * Convert the response plaintext bytes to a string */ return new String(resp.getPlaintext().array(), Charset.forName("UTF-8")); }
/** * Decodes the encrypted token and attempts to decrypt it using AWS KMS. If * successful, the token is returned. * * @param kmsClient KMS client * @param encryptedToken Token to decode and decrypt * @return Decrypted token */ protected VaultAuthResponse decryptToken(AWSKMS kmsClient, String encryptedToken) { byte[] decodedToken; try { decodedToken = Base64.decode(encryptedToken); } catch (IllegalArgumentException iae) { throw new VaultClientException("Encrypted token not Base64 encoded", iae); } final DecryptRequest request = new DecryptRequest().withCiphertextBlob(ByteBuffer.wrap(decodedToken)); final DecryptResult result = kmsClient.decrypt(request); final String decryptedAuthData = new String(result.getPlaintext().array(), Charset.forName("UTF-8")); return gson.fromJson(decryptedAuthData, VaultAuthResponse.class); }
@Test public void testAwsPrivateKeyStore() throws Exception { String bucketName = "my_bucket"; String keyName = "my_key"; String expected = "my_value"; AmazonS3 s3 = Mockito.mock(AmazonS3.class); AWSKMS kms = Mockito.mock(AWSKMS.class); S3Object s3Object = Mockito.mock(S3Object.class); Mockito.when(s3.getObject(bucketName, keyName)).thenReturn(s3Object); InputStream is = new ByteArrayInputStream( expected.getBytes() ); S3ObjectInputStream s3ObjectInputStream = new S3ObjectInputStream(is, null); Mockito.when(s3Object.getObjectContent()).thenReturn(s3ObjectInputStream); String result = expected; ByteBuffer buffer = ByteBuffer.wrap(result.getBytes()); DecryptResult decryptResult = Mockito.mock(DecryptResult.class); Mockito.when(kms.decrypt(Mockito.any(DecryptRequest.class))).thenReturn(decryptResult); Mockito.when(decryptResult.getPlaintext()).thenReturn(buffer); AwsPrivateKeyStore awsPrivateKeyStore = new AwsPrivateKeyStore(s3, kms); String actual = awsPrivateKeyStore.getApplicationSecret(bucketName, keyName); Assert.assertEquals(actual, expected); }
@Before public void setUp() throws Exception { mockKms = mock(AWSKMS.class); textEncryptor = new KmsTextEncryptor(mockKms, KMS_KEY_ID); expectedEncryptRequest = new EncryptRequest(); expectedEncryptRequest.setKeyId(KMS_KEY_ID); expectedEncryptRequest.setPlaintext(wrap(PLAINTEXT.getBytes())); encryptResult = new EncryptResult(); encryptResult.setCiphertextBlob(wrap(CIPHER_TEXT.getBytes())); when(mockKms.encrypt(any(EncryptRequest.class))).thenReturn(encryptResult); expectedDecryptRequest = new DecryptRequest(); expectedDecryptRequest.setCiphertextBlob(wrap(CIPHER_TEXT.getBytes())); decryptResult = new DecryptResult(); decryptResult.setPlaintext(wrap(PLAINTEXT.getBytes())); when(mockKms.decrypt(any(DecryptRequest.class))).thenReturn(decryptResult); }
@Override public String decrypt(AwsParamsDto awsParamsDto, String base64ciphertextBlob) { // Construct a new AWS KMS service client using the specified client configuration. // A credentials provider chain will be used that searches for credentials in this order: // - Environment Variables - AWS_ACCESS_KEY_ID and AWS_SECRET_KEY // - Java System Properties - aws.accessKeyId and aws.secretKey // - Instance Profile Credentials - delivered through the Amazon EC2 metadata service AWSKMSClient awsKmsClient = new AWSKMSClient(awsHelper.getClientConfiguration(awsParamsDto)); // Decode the base64 encoded ciphertext. ByteBuffer ciphertextBlob = ByteBuffer.wrap(Base64.decodeBase64(base64ciphertextBlob)); // Create the decrypt request. DecryptRequest decryptRequest = new DecryptRequest().withCiphertextBlob(ciphertextBlob); // Call AWS KMS decrypt service method. DecryptResult decryptResult = kmsOperations.decrypt(awsKmsClient, decryptRequest); // Get decrypted plaintext data. ByteBuffer plainText = decryptResult.getPlaintext(); // Return the plain text as a string. return new String(plainText.array(), StandardCharsets.UTF_8); }
@Override public DecryptResult decrypt(AWSKMSClient awsKmsClient, DecryptRequest decryptRequest) { // Check the cipher text. if (decryptRequest.getCiphertextBlob().equals(ByteBuffer.wrap(Base64.decodeBase64(MOCK_CIPHER_TEXT_INVALID)))) { throw new InvalidCiphertextException("(Service: AWSKMS; Status Code: 400; Error Code: InvalidCiphertextException; Request ID: NONE)"); } DecryptResult decryptResult = new DecryptResult(); // Convert the test plain text to byte buffer and set the plain text return value. decryptResult.setPlaintext(ByteBuffer.wrap(MOCK_PLAIN_TEXT.getBytes())); return decryptResult; }
@Test public void testEncryptDecrypt() throws Exception { DecryptResult mockDecryptResult = mock(DecryptResult.class); EncryptResult mockEncryptResult = mock(EncryptResult.class); when(mockKms.decrypt(isA(DecryptRequest.class))) .thenReturn(mockDecryptResult); when(mockKms.encrypt(isA(EncryptRequest.class))) .thenReturn(mockEncryptResult); Aead aead = new AwsKmsAead(mockKms, keyId); byte[] aad = Random.randBytes(20); for (int messageSize = 0; messageSize < 75; messageSize++) { byte[] message = Random.randBytes(messageSize); when(mockDecryptResult.getPlaintext()).thenReturn(ByteBuffer.wrap(message)); when(mockEncryptResult.getCiphertextBlob()).thenReturn(ByteBuffer.wrap(message)); byte[] ciphertext = aead.encrypt(message, aad); byte[] decrypted = aead.decrypt(ciphertext, aad); assertArrayEquals(message, decrypted); } }
/** * Decrypts the secured CEK via KMS; involves network calls. * * @return the CEK (in plaintext). */ private static SecretKey cekByKMS(byte[] cekSecured, String keyWrapAlgo, EncryptionMaterials materials, ContentCryptoScheme contentCryptoScheme, AWSKMS kms) { DecryptRequest kmsreq = new DecryptRequest() .withEncryptionContext(materials.getMaterialsDescription()) .withCiphertextBlob(ByteBuffer.wrap(cekSecured)); DecryptResult result = kms.decrypt(kmsreq); return new SecretKeySpec(copyAllBytesFrom(result.getPlaintext()), contentCryptoScheme.getKeyGeneratorAlgorithm()); }
private String decryptString(byte[] encryptedString) { DecryptRequest request = new DecryptRequest(); LOGGER.fine("decrypting with kms"); if (null != this.kmsEncryptionContextKey && null != this.kmsSecretName) { LOGGER.info("decrypting with context"); request.addEncryptionContextEntry(this.kmsEncryptionContextKey, this.kmsSecretName); } request.setCiphertextBlob(ByteBuffer.wrap(encryptedString)); DecryptResult decryptResult = this.amazonKmsClientBuilder.build().decrypt(request); LOGGER.fine("decrypted with kms"); return charset.decode(decryptResult.getPlaintext()).toString(); }
@Test public void passwordUsesTheS3Bucket() throws Exception { S3Object mockS3Object = mock(S3Object.class); AmazonS3Client mockClient = mock(AmazonS3Client.class); when(mockClientBuilder.build()).thenReturn(mockClient); when(mockClient.getObject(any(GetObjectRequest.class))).thenReturn(mockS3Object); AWSKMSClient mockKmsClient = mock(AWSKMSClient.class); when(mockKmsClientBuilder.build()).thenReturn(mockKmsClient); S3ObjectInputStream mockS3ObjectInputStream = mock(S3ObjectInputStream.class); when(mockS3Object.getObjectContent()).thenReturn(mockS3ObjectInputStream); when(mockS3ObjectInputStream.read(new byte[anyInt()], anyInt(), anyByte())) .thenAnswer(new WriteBufferAnswer("encryptedPassword".getBytes())) .thenReturn(-1); DecryptResult result = new DecryptResult(); CharsetEncoder charsetEncoder = Charset.forName("UTF-8").newEncoder(); result.setPlaintext(charsetEncoder.encode(CharBuffer.wrap("password"))); when(mockKmsClient.decrypt(any(DecryptRequest.class))).thenReturn(result); Secret secret = test.getPassword(); // have we got the expected password assertThat(secret.getPlainText()).isEqualTo("password"); // have we used the bucket ArgumentCaptor<GetObjectRequest> capturedObjectRequest = ArgumentCaptor.forClass(GetObjectRequest.class); verify(mockClient).getObject(capturedObjectRequest.capture()); assertThat(capturedObjectRequest.getValue().getBucketName()).isEqualTo("bucketUri"); assertThat(capturedObjectRequest.getValue().getS3ObjectId().getKey()).isEqualTo("/bucketPath"); // have we used kms to decrypt ArgumentCaptor<DecryptRequest> capturedDecryptRequest = ArgumentCaptor.forClass(DecryptRequest.class); verify(mockKmsClient).decrypt(capturedDecryptRequest.capture()); assertThat(capturedDecryptRequest.getValue().getEncryptionContext()).containsEntry("someEncryptContextKey", "kmsEncryptContextValue"); ByteBuffer ciphertextBlob = capturedDecryptRequest.getValue().getCiphertextBlob(); assertThat(new String(Charset.forName("UTF-8").decode(ciphertextBlob).array())).isEqualTo("encryptedPassword"); }
@Test public void closesIfIOExceptionWhileReading() throws Exception { AmazonS3Client mockClient = mock(AmazonS3Client.class); when(mockClientBuilder.build()).thenReturn(mockClient); AWSKMSClient mockKmsClient = mock(AWSKMSClient.class); when(mockKmsClientBuilder.build()).thenReturn(mockKmsClient); S3Object mockS3Object = mock(S3Object.class); when(mockClient.getObject(any(GetObjectRequest.class))).thenReturn(mockS3Object); S3ObjectInputStream mockS3ObjectInputStream = mock(S3ObjectInputStream.class); when(mockS3Object.getObjectContent()).thenReturn(mockS3ObjectInputStream); when(mockS3ObjectInputStream.read(new byte[anyInt()], anyInt(), anyByte())) .thenAnswer(new WriteBufferAnswer("encryptedPassword".getBytes())) .thenThrow(new IOException("something went wrong")) .thenReturn(-1); DecryptResult result = new DecryptResult(); CharsetEncoder charsetEncoder = Charset.forName("UTF-8").newEncoder(); result.setPlaintext(charsetEncoder.encode(CharBuffer.wrap("password"))); when(mockKmsClient.decrypt(any(DecryptRequest.class))).thenReturn(result); Secret secret = null; try { secret = test.getPassword(); TestCase.fail("should have thrown exception"); } catch (AwsBucketReadingException e) { assertThat(e.getCause()).isInstanceOf(IOException.class); } // have we used the bucket ArgumentCaptor<GetObjectRequest> capturedObjectRequest = ArgumentCaptor.forClass(GetObjectRequest.class); verify(mockClient).getObject(capturedObjectRequest.capture()); assertThat(capturedObjectRequest.getValue().getBucketName()).isEqualTo("bucketUri"); assertThat(capturedObjectRequest.getValue().getS3ObjectId().getKey()).isEqualTo("/bucketPath"); // and we have closed it even if there was an exception verify(mockS3Object).close(); }
@Override public DataKey<KmsMasterKey> decryptDataKey(final CryptoAlgorithm algorithm, final Collection<? extends EncryptedDataKey> encryptedDataKeys, final Map<String, String> encryptionContext) throws UnsupportedProviderException, AwsCryptoException { final List<Exception> exceptions = new ArrayList<>(); for (final EncryptedDataKey edk : encryptedDataKeys) { try { final DecryptResult decryptResult = kms_.decrypt( new DecryptRequest() .withCiphertextBlob(ByteBuffer.wrap(edk.getEncryptedDataKey())) .withEncryptionContext(encryptionContext) .withGrantTokens(grantTokens_)); if (decryptResult.getKeyId().equals(id_)) { final byte[] rawKey = new byte[algorithm.getDataKeyLength()]; decryptResult.getPlaintext().get(rawKey); if (decryptResult.getPlaintext().remaining() > 0) { throw new IllegalStateException("Received an unexpected number of bytes from KMS"); } return new DataKey<>( new SecretKeySpec(rawKey, algorithm.getDataKeyAlgo()), edk.getEncryptedDataKey(), edk.getProviderInformation(), this); } } catch (final AmazonServiceException awsex) { exceptions.add(awsex); } } throw buildCannotDecryptDksException(exceptions); }
private EncryptResult encrypt0(EncryptRequest req) throws AmazonServiceException, AmazonClientException { final byte[] cipherText = new byte[512]; rnd.nextBytes(cipherText); DecryptResult dec = new DecryptResult(); dec.withKeyId(req.getKeyId()).withPlaintext(req.getPlaintext().asReadOnlyBuffer()); ByteBuffer ctBuff = ByteBuffer.wrap(cipherText); results_.put(new DecryptMapKey(ctBuff, req.getEncryptionContext()), dec); String arn = retrieveArn(req.getKeyId()); return new EncryptResult().withCiphertextBlob(ctBuff).withKeyId(arn); }
/** * Decrypts the given encrypted bytes with the given encryption context. * Assumes the runtime has access to the desired AWS environment. * * @param region the region * @param encryptionContext optional encryption context * @param encryptedBytes the encrypted bytes * @return the decrypted bytes */ public static byte[] decrypt(Region region, Map<String, String> encryptionContext, byte[] encryptedBytes) { DecryptRequest decryptRequest = new DecryptRequest(); decryptRequest.setEncryptionContext(encryptionContext); decryptRequest.setCiphertextBlob(ByteBuffer.wrap(encryptedBytes)); AWSKMSClient client = new AWSKMSClient(); client.setRegion(region); DecryptResult decryptResult = client.decrypt(decryptRequest); return decryptResult.getPlaintext().array(); }
@Bean AWSKMS kms() { final AWSKMS mock = mock(AWSKMS.class); when(mock.decrypt(any(DecryptRequest.class))).thenAnswer((Answer<DecryptResult>) invocation -> new DecryptResult().withPlaintext(ByteBuffer.wrap(KmsEncryptionIntegrationConfigurationTest.PLAINTEXT.getBytes()))); return mock; }
@Override public DecryptionMaterials getDecryptionMaterials(EncryptionContext context) { final Map<String, String> materialDescription = context.getMaterialDescription(); final Map<String, String> ec = new HashMap<>(); final String providedEncAlg = materialDescription.get(CONTENT_KEY_ALGORITHM); final String providedSigAlg = materialDescription.get(SIGNING_KEY_ALGORITHM); ec.put("*" + CONTENT_KEY_ALGORITHM + "*", providedEncAlg); ec.put("*" + SIGNING_KEY_ALGORITHM + "*", providedSigAlg); populateKmsEcFromEc(context, ec); DecryptRequest request = appendUserAgent(new DecryptRequest()); request.setCiphertextBlob(ByteBuffer.wrap(Base64.decode(materialDescription.get(ENVELOPE_KEY)))); request.setEncryptionContext(ec); final DecryptResult decryptResult = kms.decrypt(request); validateEncryptionKeyId(decryptResult.getKeyId(), context); final Hkdf kdf; try { kdf = Hkdf.getInstance(KDF_ALG); } catch (NoSuchAlgorithmException e) { throw new DynamoDBMappingException(e); } kdf.init(toArray(decryptResult.getPlaintext())); final String[] encAlgParts = providedEncAlg.split("/", 2); int encLength = encAlgParts.length == 2 ? Integer.parseInt(encAlgParts[1]) : 256; final String[] sigAlgParts = providedSigAlg.split("/", 2); int sigLength = sigAlgParts.length == 2 ? Integer.parseInt(sigAlgParts[1]) : 256; final SecretKey encryptionKey = new SecretKeySpec(kdf.deriveKey(KDF_ENC_INFO, encLength / 8), encAlgParts[0]); final SecretKey macKey = new SecretKeySpec(kdf.deriveKey(KDF_SIG_INFO, sigLength / 8), sigAlgParts[0]); return new SymmetricRawMaterials(encryptionKey, macKey, materialDescription); }
@Override public DecryptResult decrypt(DecryptRequest req) throws AmazonServiceException, AmazonClientException { DecryptResult result = results_.get(new DecryptMapKey(req)); if (result != null) { return result; } else { throw new InvalidCiphertextException("Invalid Ciphertext"); } }
@Override public EncryptResult encrypt(EncryptRequest req) throws AmazonServiceException, AmazonClientException { final byte[] cipherText = new byte[512]; rnd.nextBytes(cipherText); DecryptResult dec = new DecryptResult(); dec.withKeyId(req.getKeyId()).withPlaintext(req.getPlaintext().asReadOnlyBuffer()); ByteBuffer ctBuff = ByteBuffer.wrap(cipherText); results_.put(new DecryptMapKey(ctBuff, req.getEncryptionContext()), dec); return new EncryptResult().withCiphertextBlob(ctBuff).withKeyId(req.getKeyId()); }
@Test public void doesNotUseEncryptContextIfNotProvided() throws Exception { AwsBucketCredentialsImpl test = new AwsBucketCredentialsImpl(CredentialsScope.GLOBAL, "myId", "EU_WEST_1", "bucketUri", "/bucketPath", "username", true, "mydescription", null, "kmsEncryptContextValue", true, "host", "9000"); Whitebox.setInternalState(test, "amazonS3ClientBuilder", mockClientBuilder); Whitebox.setInternalState(test, "amazonKmsClientBuilder", mockKmsClientBuilder); AmazonS3Client mockClient = mock(AmazonS3Client.class); when(mockClientBuilder.build()).thenReturn(mockClient); AWSKMSClient mockKmsClient = mock(AWSKMSClient.class); when(mockKmsClientBuilder.build()).thenReturn(mockKmsClient); S3Object mockS3Object = mock(S3Object.class); when(mockClient.getObject(any(GetObjectRequest.class))).thenReturn(mockS3Object); S3ObjectInputStream mockS3ObjectInputStream = mock(S3ObjectInputStream.class); when(mockS3Object.getObjectContent()).thenReturn(mockS3ObjectInputStream); when(mockS3ObjectInputStream.read(new byte[anyInt()], anyInt(), anyByte())) .thenAnswer(new WriteBufferAnswer("encryptedPassword".getBytes())) .thenReturn(-1); DecryptResult result = new DecryptResult(); CharsetEncoder charsetEncoder = Charset.forName("UTF-8").newEncoder(); result.setPlaintext(charsetEncoder.encode(CharBuffer.wrap("password"))); when(mockKmsClient.decrypt(any(DecryptRequest.class))).thenReturn(result); Secret secret = test.getPassword(); // have we got the expected password assertThat(secret.getPlainText()).isEqualTo("password"); // have we used the bucket ArgumentCaptor<GetObjectRequest> capturedObjectRequest = ArgumentCaptor.forClass(GetObjectRequest.class); verify(mockClient).getObject(capturedObjectRequest.capture()); assertThat(capturedObjectRequest.getValue().getBucketName()).isEqualTo("bucketUri"); assertThat(capturedObjectRequest.getValue().getS3ObjectId().getKey()).isEqualTo("/bucketPath"); // have we used kms to decrypt ArgumentCaptor<DecryptRequest> capturedDecryptRequest = ArgumentCaptor.forClass(DecryptRequest.class); verify(mockKmsClient).decrypt(capturedDecryptRequest.capture()); assertThat(capturedDecryptRequest.getValue().getEncryptionContext()).isEmpty(); ByteBuffer ciphertextBlob = capturedDecryptRequest.getValue().getCiphertextBlob(); assertThat(new String(Charset.forName("UTF-8").decode(ciphertextBlob).array())).isEqualTo("encryptedPassword"); verify(mockS3Object).close(); }
protected void mockDecrypt(AWSKMSClient kmsClient, final String toDecrypt) { DecryptResult decryptResult = new DecryptResult(); decryptResult.setPlaintext(ByteBuffer.wrap(toDecrypt.getBytes())); when(kmsClient.decrypt(any(DecryptRequest.class))).thenReturn(decryptResult); }
@Override public DecryptResult decrypt(AWSKMSClient awsKmsClient, DecryptRequest decryptRequest) { // Call AWS KMS decrypt service method. return awsKmsClient.decrypt(decryptRequest); }
protected ByteBuffer decryptKeyWithKMS(byte[] encryptedKeyBytes, Map<String, String> context) { ByteBuffer blob = ByteBuffer.wrap(encryptedKeyBytes); DecryptResult decryptResult = awskmsClient.decrypt(new DecryptRequest().withCiphertextBlob(blob).withEncryptionContext(context)); return decryptResult.getPlaintext(); }
/** * Executes the decrypt request by calling the AWS KMS service. * * @param awsKmsClient the client for accessing the AWS KMS service * @param decryptRequest the decrypt request * * @return the response from the decrypt service method, as returned by AWS KMS service */ public DecryptResult decrypt(AWSKMSClient awsKmsClient, DecryptRequest decryptRequest);