1
1
/*
2
- * Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ * Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
5
5
* in compliance with the License. A copy of the License is located at
36
36
* <p>
37
37
* Arguments:
38
38
* <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
40
41
* <li>File Name
41
42
* </ol>
42
43
*
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.
49
54
*/
50
55
public class EscrowedEncryptExample {
51
56
private static PublicKey publicEscrowKey ;
52
57
private static PrivateKey privateEscrowKey ;
53
58
54
59
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 .
57
62
generateEscrowKeyPair ();
58
63
59
64
final String kmsArn = args [0 ];
@@ -66,23 +71,25 @@ public static void main(final String[] args) throws Exception {
66
71
}
67
72
68
73
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
70
75
// 1. Instantiate the SDK
71
76
final AwsCrypto crypto = new AwsCrypto ();
72
77
73
- // 2. Instantiate the providers
78
+ // 2. Instantiate a KMS master key provider
74
79
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.
77
84
final JceMasterKey escrowPub = JceMasterKey .getInstance (publicEscrowKey , null , "Escrow" , "Escrow" ,
78
85
"RSA/ECB/OAEPWithSHA-512AndMGF1Padding" );
79
86
80
- // 3 . Combine the providers into a single one
87
+ // 4 . Combine the providers into a single master key provider
81
88
final MasterKeyProvider <?> provider = MultipleProviderFactory .buildMultiProvider (kms , escrowPub );
82
89
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 .
86
93
final FileInputStream in = new FileInputStream (fileName );
87
94
final FileOutputStream out = new FileOutputStream (fileName + ".encrypted" );
88
95
final CryptoOutputStream <?> encryptingStream = crypto .createEncryptingStream (provider , out );
@@ -93,25 +100,26 @@ private static void standardEncrypt(final String kmsArn, final String fileName)
93
100
}
94
101
95
102
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
98
104
99
105
// 1. Instantiate the SDK
100
106
final AwsCrypto crypto = new AwsCrypto ();
101
107
102
- // 2. Instantiate the providers
108
+ // 2. Instantiate a KMS master key provider
103
109
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.
106
114
final JceMasterKey escrowPub = JceMasterKey .getInstance (publicEscrowKey , null , "Escrow" , "Escrow" ,
107
115
"RSA/ECB/OAEPWithSHA-512AndMGF1Padding" );
108
116
109
- // 3 . Combine the providers into a single one
117
+ // 4 . Combine the providers into a single master key provider
110
118
final MasterKeyProvider <?> provider = MultipleProviderFactory .buildMultiProvider (kms , escrowPub );
111
119
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 .
115
123
final FileInputStream in = new FileInputStream (fileName + ".encrypted" );
116
124
final FileOutputStream out = new FileOutputStream (fileName + ".decrypted" );
117
125
final CryptoOutputStream <?> decryptingStream = crypto .createDecryptingStream (provider , out );
@@ -121,19 +129,20 @@ private static void standardDecrypt(final String kmsArn, final String fileName)
121
129
}
122
130
123
131
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.
125
134
126
135
// 1. Instantiate the SDK
127
136
final AwsCrypto crypto = new AwsCrypto ();
128
137
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
131
140
final JceMasterKey escrowPriv = JceMasterKey .getInstance (publicEscrowKey , privateEscrowKey , "Escrow" , "Escrow" ,
132
141
"RSA/ECB/OAEPWithSHA-512AndMGF1Padding" );
133
142
134
143
// 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 .
137
146
final FileInputStream in = new FileInputStream (fileName + ".encrypted" );
138
147
final FileOutputStream out = new FileOutputStream (fileName + ".deescrowed" );
139
148
final CryptoOutputStream <?> decryptingStream = crypto .createDecryptingStream (escrowPriv , out );
0 commit comments