View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with this
4    * work for additional information regarding copyright ownership. The ASF
5    * licenses this file to you under the Apache License, Version 2.0 (the
6    * "License"); you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  package org.apache.hadoop.hbase.io.crypto;
18  
19  import static org.junit.Assert.*;
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.ByteArrayOutputStream;
23  import java.security.Key;
24  
25  import javax.crypto.spec.SecretKeySpec;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.hadoop.conf.Configuration;
30  import org.apache.hadoop.hbase.HBaseConfiguration;
31  import org.apache.hadoop.hbase.HConstants;
32  import org.apache.hadoop.hbase.testclassification.SmallTests;
33  import org.apache.hadoop.hbase.util.Bytes;
34  import org.junit.Test;
35  import org.junit.experimental.categories.Category;
36  
37  @Category(SmallTests.class)
38  public class TestEncryption {
39  
40    private static final Log LOG = LogFactory.getLog(TestEncryption.class);
41  
42    @Test
43    public void testSmallBlocks() throws Exception {
44      byte[] key = new byte[16];
45      Bytes.random(key);
46      byte[] iv = new byte[16];
47      Bytes.random(iv);
48      for (int size: new int[] { 4, 8, 16, 32, 64, 128, 256, 512 } ) {
49        checkTransformSymmetry(key, iv, getRandomBlock(size));
50      }
51    }
52  
53    @Test
54    public void testLargeBlocks() throws Exception {
55      byte[] key = new byte[16];
56      Bytes.random(key);
57      byte[] iv = new byte[16];
58      Bytes.random(iv);
59      for (int size: new int[] { 256 * 1024, 512 * 1024, 1024 * 1024 } ) {
60        checkTransformSymmetry(key, iv, getRandomBlock(size));
61      }
62    }
63  
64    @Test
65    public void testOddSizedBlocks() throws Exception {
66      byte[] key = new byte[16];
67      Bytes.random(key);
68      byte[] iv = new byte[16];
69      Bytes.random(iv);
70      for (int size: new int[] { 3, 7, 11, 23, 47, 79, 119, 175 } ) {
71        checkTransformSymmetry(key, iv, getRandomBlock(size));
72      }
73    }
74  
75    @Test
76    public void testTypicalHFileBlocks() throws Exception {
77      byte[] key = new byte[16];
78      Bytes.random(key);
79      byte[] iv = new byte[16];
80      Bytes.random(iv);
81      for (int size: new int[] { 4 * 1024, 8 * 1024, 64 * 1024, 128 * 1024 } ) {
82        checkTransformSymmetry(key, iv, getRandomBlock(size));
83      }
84    }
85  
86    private void checkTransformSymmetry(byte[] keyBytes, byte[] iv, byte[] plaintext)
87        throws Exception {
88      LOG.info("checkTransformSymmetry: AES, plaintext length = " + plaintext.length);
89  
90      Configuration conf = HBaseConfiguration.create();
91      String algorithm =
92          conf.get(HConstants.CRYPTO_KEY_ALGORITHM_CONF_KEY, HConstants.CIPHER_AES);
93      Cipher aes = Encryption.getCipher(conf, algorithm);
94      Key key = new SecretKeySpec(keyBytes, algorithm);
95  
96      Encryptor e = aes.getEncryptor();
97      e.setKey(key);
98      e.setIv(iv);
99      e.reset();
100     ByteArrayOutputStream encOut = new ByteArrayOutputStream();
101     Encryption.encrypt(encOut, plaintext, 0, plaintext.length, e);
102     byte[] encrypted = encOut.toByteArray();
103 
104     Decryptor d = aes.getDecryptor();
105     d.setKey(key);
106     d.setIv(iv);
107     d.reset();
108     ByteArrayInputStream encIn = new ByteArrayInputStream(encrypted);
109     ByteArrayOutputStream decOut = new ByteArrayOutputStream();
110     Encryption.decrypt(decOut, encIn, plaintext.length, d);
111 
112     byte[] result = decOut.toByteArray();
113     assertEquals("Decrypted result has different length than plaintext",
114       result.length, plaintext.length);
115     assertTrue("Transformation was not symmetric",
116       Bytes.equals(result, plaintext));
117   }
118 
119   private byte[] getRandomBlock(int size) {
120     byte[] b = new byte[size];
121     Bytes.random(b);
122     return b;
123   }
124 
125 }