Skip to content

Commit ada84e8

Browse files
Adding example for DER formatted RSA keys
1 parent 66e8dab commit ada84e8

File tree

5 files changed

+150
-8
lines changed

5 files changed

+150
-8
lines changed

src/examples/README.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ you need to describe how you want the library to protect your data keys.
2121
You can do this using
2222
[keyrings](#keyrings) or [cryptographic materials managers](#cryptographic-materials-managers),
2323
or using [master key providers](#master-key-providers).
24-
These examples will show you how yo use the configuration tools that we include for you
25-
as well as how to create some of your own. We start with AWS KMS examples, then show
26-
how to use other wrapping keys.
24+
These examples will show you how to use the configuration tools that we include for you
25+
as well as how to create some of your own.
26+
We start with AWS KMS examples, then show how to use other wrapping keys.
2727

2828
* Using AWS Key Management Service (AWS KMS)
2929
* How to use a single AWS KMS CMK
@@ -43,6 +43,8 @@ how to use other wrapping keys.
4343
* [with keyrings](./java/com/amazonaws/crypto/examples/keyring/rawrsa/RawRsa.java)
4444
* How to encrypt with a raw RSA public key wrapping key without access to the private key
4545
* [with keyrings](./java/com/amazonaws/crypto/examples/keyring/rawrsa/PublicPrivateKeySeparate.java)
46+
* How to use a raw RSA wrapping key when the key is DER encoded
47+
* [with keyrings](./java/com/amazonaws/crypto/examples/keyring/rawrsa/RawRsaDerEncoded.java)
4648
* Combining wrapping keys
4749
* How to combine AWS KMS with an offline escrow key
4850
* [with keyrings](./java/com/amazonaws/crypto/examples/keyring/multi/AwsKmsWithEscrow.java)

src/examples/java/com/amazonaws/crypto/examples/keyring/rawaes/RawAes.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public static void run(final byte[] sourcePlaintext) {
4848
//
4949
// In practice, you should get this key from a secure key management system such as an HSM.
5050
SecureRandom rnd = new SecureRandom();
51-
byte[] rawKey = new byte[16]; // 128 bits
51+
byte[] rawKey = new byte[32]; // 256 bits
5252
rnd.nextBytes(rawKey);
5353
SecretKey key = new SecretKeySpec(rawKey, "AES");
5454

src/examples/java/com/amazonaws/crypto/examples/keyring/rawrsa/PublicPrivateKeySeparate.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
/**
2323
* One of the benefits of asymmetric encryption
2424
* is that you can encrypt with just the public key.
25-
* This means that you give someone the ability to encrypt
25+
* This means that you can give someone the ability to encrypt
2626
* without giving them the ability to decrypt.
2727
* <p>
2828
* The raw RSA keyring supports encrypt-only operations
@@ -31,7 +31,10 @@
3131
* This example shows how to construct and use the raw RSA keyring
3232
* to encrypt with only the public key and decrypt with the private key.
3333
* <p>
34-
* https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html#use-raw-aes-keyring
34+
* If your RSA key is in DER format,
35+
* see the {@link RawRsaDerEncoded} example.
36+
* <p>
37+
* https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html#use-raw-rsa-keyring
3538
* <p>
3639
* In this example, we use the one-step encrypt and decrypt APIs.
3740
*/
@@ -113,7 +116,7 @@ public static void run(final byte[] sourcePlaintext) throws GeneralSecurityExcep
113116
.keyring(publicKeyKeyring)
114117
.ciphertext(ciphertext)
115118
.build());
116-
assert false;
119+
throw new AssertionError("The public key can never decrypt!");
117120
} catch (AwsCryptoException ex) {
118121
// The public key cannot decrypt.
119122
// Reaching this point means everything is working as expected.

src/examples/java/com/amazonaws/crypto/examples/keyring/rawrsa/RawRsa.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121
/**
2222
* This examples shows how to configure and use a raw RSA keyring using a pre-loaded RSA key pair.
2323
* <p>
24-
* https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html#use-raw-aes-keyring
24+
* If your RSA key is in DER format,
25+
* see the {@link RawRsaDerEncoded} example.
26+
* <p>
27+
* https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html#use-raw-rsa-keyring
2528
* <p>
2629
* In this example, we use the one-step encrypt and decrypt APIs.
2730
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package com.amazonaws.crypto.examples.keyring.rawrsa;
5+
6+
import com.amazonaws.encryptionsdk.AwsCrypto;
7+
import com.amazonaws.encryptionsdk.AwsCryptoResult;
8+
import com.amazonaws.encryptionsdk.DecryptRequest;
9+
import com.amazonaws.encryptionsdk.EncryptRequest;
10+
import com.amazonaws.encryptionsdk.keyrings.Keyring;
11+
import com.amazonaws.encryptionsdk.keyrings.RawRsaKeyringBuilder;
12+
import com.amazonaws.encryptionsdk.keyrings.StandardKeyrings;
13+
14+
import java.security.GeneralSecurityException;
15+
import java.security.KeyFactory;
16+
import java.security.KeyPair;
17+
import java.security.KeyPairGenerator;
18+
import java.security.PrivateKey;
19+
import java.security.PublicKey;
20+
import java.security.spec.PKCS8EncodedKeySpec;
21+
import java.security.spec.X509EncodedKeySpec;
22+
import java.util.Arrays;
23+
import java.util.HashMap;
24+
import java.util.Map;
25+
26+
/**
27+
* When you store RSA keys, you have to serialize them somehow.
28+
* <p>
29+
* This example shows how to configure and use a raw RSA keyring using a DER-encoded RSA private key.
30+
* <p>
31+
* The most commonly used encodings for RSA keys tend to be PEM and DER.
32+
* For parsing PEM-encoded keys, see https://www.bouncycastle.org/docs/pkixdocs1.4/org/bouncycastle/openssl/PEMParser.html
33+
* <p>
34+
* https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html#use-raw-rsa-keyring
35+
* <p>
36+
* In this example, we use the one-step encrypt and decrypt APIs.
37+
*/
38+
public class RawRsaDerEncoded {
39+
40+
/**
41+
* Demonstrate an encrypt/decrypt cycle using a raw RSA keyring loaded from a DER-encoded key.
42+
*
43+
* @param sourcePlaintext Plaintext to encrypt
44+
*/
45+
public static void run(final byte[] sourcePlaintext) throws GeneralSecurityException {
46+
// Instantiate the AWS Encryption SDK.
47+
final AwsCrypto awsEncryptionSdk = new AwsCrypto();
48+
49+
// Prepare your encryption context.
50+
// https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/concepts.html#encryption-context
51+
final Map<String, String> encryptionContext = new HashMap<>();
52+
encryptionContext.put("encryption", "context");
53+
encryptionContext.put("is not", "secret");
54+
encryptionContext.put("but adds", "useful metadata");
55+
encryptionContext.put("that can help you", "be confident that");
56+
encryptionContext.put("the data you are handling", "is what you think it is");
57+
58+
// Generate an RSA key pair to use with your keyring.
59+
// In practice, you should get this key from a secure key management system such as an HSM.
60+
final KeyPairGenerator kg = KeyPairGenerator.getInstance("RSA");
61+
// The National Institute of Standards and Technology (NIST) recommends a minimum of 2048-bit keys for RSA.
62+
// https://www.nist.gov/publications/transitioning-use-cryptographic-algorithms-and-key-lengths
63+
kg.initialize(4096);
64+
final KeyPair keyPair = kg.generateKeyPair();
65+
66+
// Serialize the RSA keys to DER encoding.
67+
// This or PEM encoding is likely to be what you get from your key management system in practice.
68+
byte[] publicKeyEncoded = keyPair.getPublic().getEncoded();
69+
byte[] privateKeyEncoded = keyPair.getPrivate().getEncoded();
70+
71+
final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
72+
73+
// Deserialize the RSA private key.
74+
final PrivateKey privateKey = keyFactory.generatePrivate(
75+
new PKCS8EncodedKeySpec(privateKeyEncoded));
76+
77+
// Deserialize the RSA public key.
78+
final PublicKey publicKey = keyFactory.generatePublic(
79+
new X509EncodedKeySpec(publicKeyEncoded));
80+
81+
// Create the keyring that determines how your data keys are protected.
82+
final Keyring keyring = StandardKeyrings.rawRsaBuilder()
83+
// The key namespace and key name are defined by you
84+
// and are used by the raw RSA keyring
85+
// to determine whether it should attempt to decrypt
86+
// an encrypted data key.
87+
//
88+
// https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/choose-keyring.html#use-raw-rsa-keyring
89+
.keyNamespace("some managed raw keys")
90+
.keyName("my RSA wrapping key")
91+
.privateKey(privateKey)
92+
.publicKey(publicKey)
93+
// The padding scheme tells the raw RSA keyring
94+
// how to use your wrapping key to encrypt data keys.
95+
//
96+
// We recommend using OAEP_SHA256_MGF1.
97+
// You should not use PKCS1 unless you require it for backwards compatibility.
98+
.paddingScheme(RawRsaKeyringBuilder.RsaPaddingScheme.OAEP_SHA256_MGF1)
99+
.build();
100+
101+
// Encrypt your plaintext data.
102+
final AwsCryptoResult<byte[]> encryptResult = awsEncryptionSdk.encrypt(
103+
EncryptRequest.builder()
104+
.keyring(keyring)
105+
.encryptionContext(encryptionContext)
106+
.plaintext(sourcePlaintext).build());
107+
final byte[] ciphertext = encryptResult.getResult();
108+
109+
// Demonstrate that the ciphertext and plaintext are different.
110+
assert !Arrays.equals(ciphertext, sourcePlaintext);
111+
112+
// Decrypt your encrypted data using the same keyring you used on encrypt.
113+
//
114+
// We do not need to specify the encryption context on decrypt
115+
// because the header message includes the encryption context.
116+
final AwsCryptoResult<byte[]> decryptResult = awsEncryptionSdk.decrypt(
117+
DecryptRequest.builder()
118+
.keyring(keyring)
119+
.ciphertext(ciphertext).build());
120+
final byte[] decrypted = decryptResult.getResult();
121+
122+
// Demonstrate that the decrypted plaintext is identical to the original plaintext.
123+
assert Arrays.equals(decrypted, sourcePlaintext);
124+
125+
// Verify that the encryption context used in the decrypt operation includes
126+
// the encryption context that you specified when encrypting.
127+
// The AWS Encryption SDK can add pairs, so don't require an exact match.
128+
//
129+
// In production, always use a meaningful encryption context.
130+
encryptionContext.forEach((k, v) -> {
131+
assert v.equals(decryptResult.getEncryptionContext().get(k));
132+
});
133+
}
134+
}

0 commit comments

Comments
 (0)