1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.util;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.IOException;
24 import java.util.Map;
25 import java.util.concurrent.ConcurrentHashMap;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.hadoop.hbase.classification.InterfaceAudience;
30 import org.apache.hadoop.hbase.classification.InterfaceStability;
31 import org.apache.hadoop.conf.Configuration;
32 import org.apache.hadoop.hbase.HConstants;
33 import org.apache.hadoop.hbase.io.crypto.DefaultCipherProvider;
34 import org.apache.hadoop.hbase.io.crypto.Encryption;
35 import org.apache.hadoop.hbase.io.crypto.KeyStoreKeyProvider;
36 import org.apache.hadoop.hbase.security.EncryptionUtil;
37
38 @InterfaceAudience.Public
39 @InterfaceStability.Evolving
40 public class EncryptionTest {
41 private static final Log LOG = LogFactory.getLog(EncryptionTest.class);
42
43 static final Map<String, Boolean> keyProviderResults = new ConcurrentHashMap<String, Boolean>();
44 static final Map<String, Boolean> cipherProviderResults =
45 new ConcurrentHashMap<String, Boolean>();
46 static final Map<String, Boolean> cipherResults = new ConcurrentHashMap<String, Boolean>();
47
48 private EncryptionTest() {
49 }
50
51
52
53
54
55
56
57
58 public static void testKeyProvider(final Configuration conf) throws IOException {
59 String providerClassName = conf.get(HConstants.CRYPTO_KEYPROVIDER_CONF_KEY,
60 KeyStoreKeyProvider.class.getName());
61 Boolean result = keyProviderResults.get(providerClassName);
62 if (result == null) {
63 try {
64 Encryption.getKeyProvider(conf);
65 keyProviderResults.put(providerClassName, true);
66 } catch (Exception e) {
67 keyProviderResults.put(providerClassName, false);
68 throw new IOException("Key provider " + providerClassName + " failed test: " +
69 e.getMessage(), e);
70 }
71 } else if (result.booleanValue() == false) {
72 throw new IOException("Key provider " + providerClassName + " previously failed test");
73 }
74 }
75
76
77
78
79
80
81
82
83 public static void testCipherProvider(final Configuration conf) throws IOException {
84 String providerClassName = conf.get(HConstants.CRYPTO_CIPHERPROVIDER_CONF_KEY,
85 DefaultCipherProvider.class.getName());
86 Boolean result = cipherProviderResults.get(providerClassName);
87 if (result == null) {
88 try {
89 Encryption.getCipherProvider(conf);
90 cipherProviderResults.put(providerClassName, true);
91 } catch (Exception e) {
92 cipherProviderResults.put(providerClassName, false);
93 throw new IOException("Cipher provider " + providerClassName + " failed test: " +
94 e.getMessage(), e);
95 }
96 } else if (result.booleanValue() == false) {
97 throw new IOException("Cipher provider " + providerClassName + " previously failed test");
98 }
99 }
100
101
102
103
104
105
106
107
108
109
110
111 public static void testEncryption(final Configuration conf, final String cipher,
112 byte[] key) throws IOException {
113 if (cipher == null) {
114 return;
115 }
116 testKeyProvider(conf);
117 testCipherProvider(conf);
118 Boolean result = cipherResults.get(cipher);
119 if (result == null) {
120 try {
121 Encryption.Context context = Encryption.newContext(conf);
122 context.setCipher(Encryption.getCipher(conf, cipher));
123 if (key == null) {
124
125 context.setKey(context.getCipher().getRandomKey());
126 } else {
127
128 context.setKey(EncryptionUtil.unwrapKey(conf,
129 conf.get(HConstants.CRYPTO_MASTERKEY_NAME_CONF_KEY, "hbase"),
130 key));
131 }
132 byte[] iv = null;
133 if (context.getCipher().getIvLength() > 0) {
134 iv = new byte[context.getCipher().getIvLength()];
135 Bytes.random(iv);
136 }
137 byte[] plaintext = new byte[1024];
138 Bytes.random(plaintext);
139 ByteArrayOutputStream out = new ByteArrayOutputStream();
140 Encryption.encrypt(out, new ByteArrayInputStream(plaintext), context, iv);
141 byte[] ciphertext = out.toByteArray();
142 out.reset();
143 Encryption.decrypt(out, new ByteArrayInputStream(ciphertext), plaintext.length,
144 context, iv);
145 byte[] test = out.toByteArray();
146 if (!Bytes.equals(plaintext, test)) {
147 throw new IOException("Did not pass encrypt/decrypt test");
148 }
149 cipherResults.put(cipher, true);
150 } catch (Exception e) {
151 cipherResults.put(cipher, false);
152 throw new IOException("Cipher " + cipher + " failed test: " + e.getMessage(), e);
153 }
154 } else if (result.booleanValue() == false) {
155 throw new IOException("Cipher " + cipher + " previously failed test");
156 }
157 }
158 }