11/*
2- * Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+ * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
55 * in compliance with the License. A copy of the License is located at
3636 * <p>
3737 * Arguments:
3838 * <ol>
39- * <li>KMS KeyArn
40- * <li>File Name
39+ * <li>Key ARN: For help finding the Amazon Resource Name (ARN) of your KMS customer master
40+ * key (CMK), see 'Viewing Keys' at http://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html
41+ *
42+ * <li>Name of file containing plaintext data to encrypt
4143 * </ol>
4244 *
43- * Some organizations want the ability to decrypt their data even if KMS is unavailable. This
44- * program demonstrates one possible way of accomplishing this by generating an "Escrow" RSA
45- * key-pair and using that in addition to the KMS key for encryption. The organization would keep
46- * the RSA private key someplace secure (such as an offline HSM) and distribute the public key their
47- * developers. This way all standard use would use KMS for decryption, however the organization
48- * maintains the ability to decrypt all ciphertexts in a completely offline manner.
45+ * You might use AWS Key Management Service (KMS) for most encryption and decryption operations, but
46+ * still want the option of decrypting your data offline independently of KMS. This sample
47+ * demonstrates one way to do this.
48+ *
49+ * The sample encrypts data under both a KMS customer master key (CMK) and an "escrowed" RSA key pair
50+ * so that either key alone can decrypt it. You might commonly use the KMS CMK for decryption. However,
51+ * at any time, you can use the private RSA key to decrypt the ciphertext independent of KMS.
52+ *
53+ * This sample uses the JCEMasterKey class to generate a RSA public-private key pair
54+ * and saves the key pair in memory. In practice, you would store the private key in a secure offline
55+ * location, such as an offline HSM, and distribute the public key to your development team.
56+ *
4957 */
5058public class EscrowedEncryptExample {
5159 private static PublicKey publicEscrowKey ;
5260 private static PrivateKey privateEscrowKey ;
5361
5462 public static void main (final String [] args ) throws Exception {
55- // In the real world, the public key would be distributed by the organization.
56- // For this demo, we'll just generate a new random one each time.
63+ // This sample generates a new random key for each operation.
64+ // In practice, you would distribute the public key and save the private key in secure
65+ // storage.
5766 generateEscrowKeyPair ();
5867
5968 final String kmsArn = args [0 ];
@@ -66,23 +75,25 @@ public static void main(final String[] args) throws Exception {
6675 }
6776
6877 private static void standardEncrypt (final String kmsArn , final String fileName ) throws Exception {
69- // Standard user encrypting to both KMS and the escrow public key
78+ // Encrypt with the KMS CMK and the escrowed public key
7079 // 1. Instantiate the SDK
7180 final AwsCrypto crypto = new AwsCrypto ();
7281
73- // 2. Instantiate the providers
82+ // 2. Instantiate a KMS master key provider
7483 final KmsMasterKeyProvider kms = new KmsMasterKeyProvider (kmsArn );
75- // Note that the standard user does not have access to the private escrow
76- // key and so simply passes in "null"
84+
85+ // 3. Instantiate a JCE master key provider
86+ // Because the user does not have access to the private escrow key,
87+ // they pass in "null" for the private key parameter.
7788 final JceMasterKey escrowPub = JceMasterKey .getInstance (publicEscrowKey , null , "Escrow" , "Escrow" ,
7889 "RSA/ECB/OAEPWithSHA-512AndMGF1Padding" );
7990
80- // 3 . Combine the providers into a single one
91+ // 4 . Combine the providers into a single master key provider
8192 final MasterKeyProvider <?> provider = MultipleProviderFactory .buildMultiProvider (kms , escrowPub );
8293
83- // 4 . Encrypt the file
84- // To simplify the code, we'll be omitted Encryption Context this time . Production code
85- // should always use Encryption Context. Please see the other examples for more information .
94+ // 5 . Encrypt the file
95+ // To simplify the code, we omit the encryption context . Production code should always
96+ // use an encryption context. For an example, see the other SDK samples .
8697 final FileInputStream in = new FileInputStream (fileName );
8798 final FileOutputStream out = new FileOutputStream (fileName + ".encrypted" );
8899 final CryptoOutputStream <?> encryptingStream = crypto .createEncryptingStream (provider , out );
@@ -93,25 +104,27 @@ private static void standardEncrypt(final String kmsArn, final String fileName)
93104 }
94105
95106 private static void standardDecrypt (final String kmsArn , final String fileName ) throws Exception {
96- // A standard user decrypts the file. They can just use the same provider from before
97- // or could use a provider just referring to the KMS key. It doesn't matter .
107+ // Decrypt with the KMS CMK and the escrow public key. You can use a combined provider,
108+ // as shown here, or just the KMS master key provider .
98109
99110 // 1. Instantiate the SDK
100111 final AwsCrypto crypto = new AwsCrypto ();
101112
102- // 2. Instantiate the providers
113+ // 2. Instantiate a KMS master key provider
103114 final KmsMasterKeyProvider kms = new KmsMasterKeyProvider (kmsArn );
104- // Note that the standard user does not have access to the private escrow
105- // key and so simply passes in "null"
115+
116+ // 3. Instantiate a JCE master key provider
117+ // Because the user does not have access to the private
118+ // escrow key, they pass in "null" for the private key parameter.
106119 final JceMasterKey escrowPub = JceMasterKey .getInstance (publicEscrowKey , null , "Escrow" , "Escrow" ,
107120 "RSA/ECB/OAEPWithSHA-512AndMGF1Padding" );
108121
109- // 3 . Combine the providers into a single one
122+ // 4 . Combine the providers into a single master key provider
110123 final MasterKeyProvider <?> provider = MultipleProviderFactory .buildMultiProvider (kms , escrowPub );
111124
112- // 4 . Decrypt the file
113- // To simplify the code, we'll be omitted Encryption Context this time . Production code
114- // should always use Encryption Context. Please see the other examples for more information .
125+ // 5 . Decrypt the file
126+ // To simplify the code, we omit the encryption context . Production code should always
127+ // use an encryption context. For an example, see the other SDK samples .
115128 final FileInputStream in = new FileInputStream (fileName + ".encrypted" );
116129 final FileOutputStream out = new FileOutputStream (fileName + ".decrypted" );
117130 final CryptoOutputStream <?> decryptingStream = crypto .createDecryptingStream (provider , out );
@@ -121,19 +134,20 @@ private static void standardDecrypt(final String kmsArn, final String fileName)
121134 }
122135
123136 private static void escrowDecrypt (final String fileName ) throws Exception {
124- // The organization can decrypt using just the private escrow key with no calls to KMS
137+ // You can decrypt the stream using only the private key.
138+ // This method does not call KMS.
125139
126140 // 1. Instantiate the SDK
127141 final AwsCrypto crypto = new AwsCrypto ();
128142
129- // 2. Instantiate the provider
130- // Note that the organization does have access to the private escrow key and can use it.
143+ // 2. Instantiate a JCE master key provider
144+ // This method call uses the escrowed private key, not null
131145 final JceMasterKey escrowPriv = JceMasterKey .getInstance (publicEscrowKey , privateEscrowKey , "Escrow" , "Escrow" ,
132146 "RSA/ECB/OAEPWithSHA-512AndMGF1Padding" );
133147
134148 // 3. Decrypt the file
135- // To simplify the code, we'll be omitted Encryption Context this time . Production code
136- // should always use Encryption Context. Please see the other examples for more information .
149+ // To simplify the code, we omit the encryption context . Production code should always
150+ // use an encryption context. For an example, see the other SDK samples .
137151 final FileInputStream in = new FileInputStream (fileName + ".encrypted" );
138152 final FileOutputStream out = new FileOutputStream (fileName + ".deescrowed" );
139153 final CryptoOutputStream <?> decryptingStream = crypto .createDecryptingStream (escrowPriv , out );
0 commit comments