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
39+ * <li>Key ARN: To find the Amazon Resource Name of your KMS customer master key (CMK),
40+ * see 'Viewing Keys' at http://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html
4041 * <li>File Name
4142 * </ol>
4243 *
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.
44+ * AWS Key Management Service (KMS) is highly available. However, some organizations want to decrypt
45+ * their data offline and independent of KMS. This sample demonstrates one way to do this.
46+ *
47+ * This program generates an "escrowed" RSA key pair. It stores the private key in a secure offline
48+ * location, such as an offline HSM, and distributes the public key to their developers. It also
49+ * creates a KMS customer master key (CMK). The organization encrypts their data with both the
50+ * KMS CMK and the public key, so that either key alone could decrypt it.
51+ *
52+ * The team usually uses the KMS CMK for decryption. However, the organization can, at any time
53+ * use the private escrowed RSA key to decrypt the ciphertext independent of KMS.
4954 */
5055public class EscrowedEncryptExample {
5156 private static PublicKey publicEscrowKey ;
5257 private static PrivateKey privateEscrowKey ;
5358
5459 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 .
60+ // In practice , the organization would distribute the public key .
61+ // For this demo, we generate a new random key for each operation .
5762 generateEscrowKeyPair ();
5863
5964 final String kmsArn = args [0 ];
@@ -66,23 +71,25 @@ public static void main(final String[] args) throws Exception {
6671 }
6772
6873 private static void standardEncrypt (final String kmsArn , final String fileName ) throws Exception {
69- // Standard user encrypting to both KMS and the escrow public key
74+ // Standard practice: encrypt with the KMS CMK and the escrowed public key
7075 // 1. Instantiate the SDK
7176 final AwsCrypto crypto = new AwsCrypto ();
7277
73- // 2. Instantiate the providers
78+ // 2. Instantiate a KMS master key provider
7479 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"
80+
81+ // 3. Instantiate a JCE master key provider
82+ // Because the standard user does not have access to the private
83+ // escrow key, they pass in "null" for the private key parameter.
7784 final JceMasterKey escrowPub = JceMasterKey .getInstance (publicEscrowKey , null , "Escrow" , "Escrow" ,
7885 "RSA/ECB/OAEPWithSHA-512AndMGF1Padding" );
7986
80- // 3 . Combine the providers into a single one
87+ // 4 . Combine the providers into a single master key provider
8188 final MasterKeyProvider <?> provider = MultipleProviderFactory .buildMultiProvider (kms , escrowPub );
8289
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 .
90+ // 5 . Encrypt the file
91+ // To simplify the code, we omit the encryption context . Production code should always
92+ // use an encryption context. For an example, see the other SDK samples .
8693 final FileInputStream in = new FileInputStream (fileName );
8794 final FileOutputStream out = new FileOutputStream (fileName + ".encrypted" );
8895 final CryptoOutputStream <?> encryptingStream = crypto .createEncryptingStream (provider , out );
@@ -93,25 +100,26 @@ private static void standardEncrypt(final String kmsArn, final String fileName)
93100 }
94101
95102 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.
103+ // Standard practice: enncrypt with the KMS CMK and the escrow public key
98104
99105 // 1. Instantiate the SDK
100106 final AwsCrypto crypto = new AwsCrypto ();
101107
102- // 2. Instantiate the providers
108+ // 2. Instantiate a KMS master key provider
103109 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"
110+
111+ // 3. Instantiate a JCE master key provider
112+ // Because the standard user does not have access to the private
113+ // escrow key, they pass in "null" for the private key parameter.
106114 final JceMasterKey escrowPub = JceMasterKey .getInstance (publicEscrowKey , null , "Escrow" , "Escrow" ,
107115 "RSA/ECB/OAEPWithSHA-512AndMGF1Padding" );
108116
109- // 3 . Combine the providers into a single one
117+ // 4 . Combine the providers into a single master key provider
110118 final MasterKeyProvider <?> provider = MultipleProviderFactory .buildMultiProvider (kms , escrowPub );
111119
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 .
120+ // 5 . Decrypt the file
121+ // To simplify the code, we omit the encryption context . Production code should always
122+ // use an encryption context. For an example, see the other SDK samples .
115123 final FileInputStream in = new FileInputStream (fileName + ".encrypted" );
116124 final FileOutputStream out = new FileOutputStream (fileName + ".decrypted" );
117125 final CryptoOutputStream <?> decryptingStream = crypto .createDecryptingStream (provider , out );
@@ -121,19 +129,20 @@ private static void standardDecrypt(final String kmsArn, final String fileName)
121129 }
122130
123131 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
132+ // The organization can decrypt the stream using only the private escrow key.
133+ // This method does not call KMS.
125134
126135 // 1. Instantiate the SDK
127136 final AwsCrypto crypto = new AwsCrypto ();
128137
129- // 2. Instantiate the provider
130- // Note that the organization does have access to the private escrow key and can use it.
138+ // 2. Instantiate a JCE master key provider
139+ // This method call uses the escrowed private key
131140 final JceMasterKey escrowPriv = JceMasterKey .getInstance (publicEscrowKey , privateEscrowKey , "Escrow" , "Escrow" ,
132141 "RSA/ECB/OAEPWithSHA-512AndMGF1Padding" );
133142
134143 // 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 .
144+ // To simplify the code, we omit the encryption context . Production code should always
145+ // use an encryption context. For an example, see the other SDK samples .
137146 final FileInputStream in = new FileInputStream (fileName + ".encrypted" );
138147 final FileOutputStream out = new FileOutputStream (fileName + ".deescrowed" );
139148 final CryptoOutputStream <?> decryptingStream = crypto .createDecryptingStream (escrowPriv , out );
0 commit comments