1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.hadoop.hbase.io.crypto.aes;
18
19 import static org.junit.Assert.*;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.OutputStream;
24 import java.security.AccessController;
25 import java.security.NoSuchAlgorithmException;
26 import java.security.PrivilegedAction;
27 import java.security.Provider;
28 import java.security.SecureRandom;
29 import java.security.SecureRandomSpi;
30 import java.security.Security;
31
32 import javax.crypto.spec.SecretKeySpec;
33
34 import org.apache.commons.io.IOUtils;
35 import org.apache.hadoop.conf.Configuration;
36 import org.apache.hadoop.hbase.HBaseConfiguration;
37 import org.apache.hadoop.hbase.testclassification.SmallTests;
38 import org.apache.hadoop.hbase.io.crypto.Cipher;
39 import org.apache.hadoop.hbase.io.crypto.DefaultCipherProvider;
40 import org.apache.hadoop.hbase.io.crypto.Encryption;
41 import org.apache.hadoop.hbase.io.crypto.Encryptor;
42 import org.apache.hadoop.hbase.util.Bytes;
43
44 import org.junit.Test;
45 import org.junit.experimental.categories.Category;
46
47 @Category(SmallTests.class)
48 public class TestAES {
49
50
51
52 @Test
53 public void testAESAlgorithm() throws Exception {
54 Configuration conf = HBaseConfiguration.create();
55 Cipher aes = Encryption.getCipher(conf, "AES");
56 assertEquals(aes.getKeyLength(), AES.KEY_LENGTH);
57 assertEquals(aes.getIvLength(), AES.IV_LENGTH);
58 Encryptor e = aes.getEncryptor();
59 e.setKey(new SecretKeySpec(Bytes.fromHex("2b7e151628aed2a6abf7158809cf4f3c"), "AES"));
60 e.setIv(Bytes.fromHex("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"));
61
62 ByteArrayOutputStream out = new ByteArrayOutputStream();
63 OutputStream cout = e.createEncryptionStream(out);
64 cout.write(Bytes.fromHex("6bc1bee22e409f96e93d7e117393172a"));
65 cout.write(Bytes.fromHex("ae2d8a571e03ac9c9eb76fac45af8e51"));
66 cout.write(Bytes.fromHex("30c81c46a35ce411e5fbc1191a0a52ef"));
67 cout.write(Bytes.fromHex("f69f2445df4f9b17ad2b417be66c3710"));
68 cout.close();
69
70 ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
71 byte[] b = new byte[16];
72 IOUtils.readFully(in, b);
73 assertTrue("Failed #1", Bytes.equals(b, Bytes.fromHex("874d6191b620e3261bef6864990db6ce")));
74 IOUtils.readFully(in, b);
75 assertTrue("Failed #2", Bytes.equals(b, Bytes.fromHex("9806f66b7970fdff8617187bb9fffdff")));
76 IOUtils.readFully(in, b);
77 assertTrue("Failed #3", Bytes.equals(b, Bytes.fromHex("5ae4df3edbd5d35e5b4f09020db03eab")));
78 IOUtils.readFully(in, b);
79 assertTrue("Failed #4", Bytes.equals(b, Bytes.fromHex("1e031dda2fbe03d1792170a0f3009cee")));
80 }
81
82 @Test
83 public void testAlternateRNG() throws Exception {
84 Security.addProvider(new TestProvider());
85
86 Configuration conf = new Configuration();
87 conf.set(AES.RNG_ALGORITHM_KEY, "TestRNG");
88 conf.set(AES.RNG_PROVIDER_KEY, "TEST");
89 DefaultCipherProvider.getInstance().setConf(conf);
90
91 AES aes = new AES(DefaultCipherProvider.getInstance());
92 assertEquals("AES did not find alternate RNG", aes.getRNG().getAlgorithm(),
93 "TestRNG");
94 }
95
96 static class TestProvider extends Provider {
97 private static final long serialVersionUID = 1L;
98 public TestProvider() {
99 super("TEST", 1.0, "Test provider");
100 AccessController.doPrivileged(new PrivilegedAction<Object>() {
101 public Object run() {
102 put("SecureRandom.TestRNG", TestAES.class.getName() + "$TestRNG");
103 return null;
104 }
105 });
106 }
107 }
108
109
110 public static class TestRNG extends SecureRandomSpi {
111 private static final long serialVersionUID = 1L;
112 private SecureRandom rng;
113
114 public TestRNG() {
115 try {
116 rng = java.security.SecureRandom.getInstance("SHA1PRNG");
117 } catch (NoSuchAlgorithmException e) {
118 fail("Unable to create SecureRandom instance");
119 }
120 }
121
122 @Override
123 protected void engineSetSeed(byte[] seed) {
124 rng.setSeed(seed);
125 }
126
127 @Override
128 protected void engineNextBytes(byte[] bytes) {
129 rng.nextBytes(bytes);
130 }
131
132 @Override
133 protected byte[] engineGenerateSeed(int numBytes) {
134 return rng.generateSeed(numBytes);
135 }
136 }
137
138 }