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.SmallTests;
32  import org.apache.hadoop.hbase.util.Bytes;
33  import org.junit.Test;
34  import org.junit.experimental.categories.Category;
35  
36  @Category(SmallTests.class)
37  public class TestEncryption {
38  
39    private static final Log LOG = LogFactory.getLog(TestEncryption.class);
40  
41    @Test
42    public void testSmallBlocks() throws Exception {
43      byte[] key = new byte[16];
44      Bytes.random(key);
45      byte[] iv = new byte[16];
46      Bytes.random(iv);
47      for (int size: new int[] { 4, 8, 16, 32, 64, 128, 256, 512 } ) {
48        checkTransformSymmetry(key, iv, getRandomBlock(size));
49      }
50    }
51  
52    @Test
53    public void testLargeBlocks() throws Exception {
54      byte[] key = new byte[16];
55      Bytes.random(key);
56      byte[] iv = new byte[16];
57      Bytes.random(iv);
58      for (int size: new int[] { 256 * 1024, 512 * 1024, 1024 * 1024 } ) {
59        checkTransformSymmetry(key, iv, getRandomBlock(size));
60      }
61    }
62  
63    @Test
64    public void testOddSizedBlocks() throws Exception {
65      byte[] key = new byte[16];
66      Bytes.random(key);
67      byte[] iv = new byte[16];
68      Bytes.random(iv);
69      for (int size: new int[] { 3, 7, 11, 23, 47, 79, 119, 175 } ) {
70        checkTransformSymmetry(key, iv, getRandomBlock(size));
71      }
72    }
73  
74    @Test
75    public void testTypicalHFileBlocks() throws Exception {
76      byte[] key = new byte[16];
77      Bytes.random(key);
78      byte[] iv = new byte[16];
79      Bytes.random(iv);
80      for (int size: new int[] { 4 * 1024, 8 * 1024, 64 * 1024, 128 * 1024 } ) {
81        checkTransformSymmetry(key, iv, getRandomBlock(size));
82      }
83    }
84  
85    private void checkTransformSymmetry(byte[] keyBytes, byte[] iv, byte[] plaintext)
86        throws Exception {
87      LOG.info("checkTransformSymmetry: AES, plaintext length = " + plaintext.length);
88  
89      Configuration conf = HBaseConfiguration.create();
90      Cipher aes = Encryption.getCipher(conf, "AES");
91      Key key = new SecretKeySpec(keyBytes, "AES");
92  
93      Encryptor e = aes.getEncryptor();
94      e.setKey(key);
95      e.setIv(iv);
96      e.reset();
97      ByteArrayOutputStream encOut = new ByteArrayOutputStream();
98      Encryption.encrypt(encOut, plaintext, 0, plaintext.length, e);
99      byte[] encrypted = encOut.toByteArray();
100 
101     Decryptor d = aes.getDecryptor();
102     d.setKey(key);
103     d.setIv(iv);
104     d.reset();
105     ByteArrayInputStream encIn = new ByteArrayInputStream(encrypted);
106     ByteArrayOutputStream decOut = new ByteArrayOutputStream();
107     Encryption.decrypt(decOut, encIn, plaintext.length, d);
108 
109     byte[] result = decOut.toByteArray();
110     assertEquals("Decrypted result has different length than plaintext",
111       result.length, plaintext.length);
112     assertTrue("Transformation was not symmetric",
113       Bytes.equals(result, plaintext));
114   }
115 
116   private byte[] getRandomBlock(int size) {
117     byte[] b = new byte[size];
118     Bytes.random(b);
119     return b;
120   }
121 
122 }