blob: 3f9ca0b3c8a64c7f09059ee25a13138efc4fa431 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.orc;
import java.nio.charset.StandardCharsets;
import org.apache.hadoop.io.BytesWritable;
import org.apache.orc.impl.HadoopShims;
import org.apache.orc.impl.LocalKey;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.security.Key;
import java.util.Random;
/**
* Test {@link InMemoryKeystore} class
*/
public class TestInMemoryKeystore {
private InMemoryKeystore memoryKeystore;
public TestInMemoryKeystore() {
super();
}
@Before
public void init() throws IOException {
// For testing, use a fixed random number generator so that everything
// is repeatable.
Random random = new Random(2);
memoryKeystore =
new InMemoryKeystore(random)
.addKey("key128", EncryptionAlgorithm.AES_CTR_128, "123".getBytes(StandardCharsets.UTF_8))
.addKey("key256", EncryptionAlgorithm.AES_CTR_256, "secret123".getBytes(StandardCharsets.UTF_8))
.addKey("key256short", EncryptionAlgorithm.AES_CTR_256, "5".getBytes(StandardCharsets.UTF_8));
}
private static String stringify(byte[] buffer) {
return new BytesWritable(buffer).toString();
}
@Test
public void testGetKeyNames() {
Assert.assertTrue(memoryKeystore.getKeyNames().contains("key128"));
Assert.assertTrue(memoryKeystore.getKeyNames().contains("key256"));
Assert.assertTrue(memoryKeystore.getKeyNames().contains("key256short"));
}
@Test
public void testGetCurrentKeyVersion() {
final HadoopShims.KeyMetadata metadata = memoryKeystore
.getCurrentKeyVersion("key256");
Assert.assertEquals("key256", metadata.getKeyName());
if (InMemoryKeystore.SUPPORTS_AES_256) {
Assert.assertEquals(EncryptionAlgorithm.AES_CTR_256, metadata.getAlgorithm());
} else {
Assert.assertEquals(EncryptionAlgorithm.AES_CTR_128, metadata.getAlgorithm());
}
Assert.assertEquals(0, metadata.getVersion());
}
@Test
public void testGetLocalKey() {
HadoopShims.KeyMetadata metadata128 = memoryKeystore
.getCurrentKeyVersion("key128");
LocalKey key128 = memoryKeystore.createLocalKey(metadata128);
// we are sure the key is the same because of the random generator.
Assert.assertEquals("39 72 2c bb f8 b9 1a 4b 90 45 c5 e6 17 5f 10 01",
stringify(key128.getEncryptedKey()));
Assert.assertEquals("46 33 66 fd 79 57 66 9a ba 4a 28 df bf 16 f2 88",
stringify(key128.getDecryptedKey().getEncoded()));
// used online aes/cbc calculator to encrypt key
Assert.assertEquals("AES", key128.getDecryptedKey().getAlgorithm());
// now decrypt the key again
Key decryptKey = memoryKeystore.decryptLocalKey(metadata128,
key128.getEncryptedKey());
Assert.assertEquals(stringify(key128.getDecryptedKey().getEncoded()),
stringify(decryptKey.getEncoded()));
HadoopShims.KeyMetadata metadata256 = memoryKeystore
.getCurrentKeyVersion("key256");
LocalKey key256 = memoryKeystore.createLocalKey(metadata256);
// this is forced by the fixed Random in the keystore for this test
if (InMemoryKeystore.SUPPORTS_AES_256) {
Assert.assertEquals("ea c3 2f 7f cd 5e cc da 5c 6e 62 fc 4e 63 85 08 0f " +
"7b 6c db 79 e5 51 ec 9c 9c c7 fc bd 60 ee 73",
stringify(key256.getEncryptedKey()));
// used online aes/cbc calculator to encrypt key
Assert.assertEquals("00 b0 1c 24 d9 03 bc 02 63 87 b3 f9 65 4e e7 a8 b8" +
" 58 eb a0 81 06 b3 61 cf f8 06 ba 30 d4 c5 36",
stringify(key256.getDecryptedKey().getEncoded()));
} else {
Assert.assertEquals("ea c3 2f 7f cd 5e cc da 5c 6e 62 fc 4e 63 85 08",
stringify(key256.getEncryptedKey()));
Assert.assertEquals("6d 1c ff 55 a5 44 75 11 fb e6 8e 08 cd 2a 10 e8",
stringify(key256.getDecryptedKey().getEncoded()));
}
Assert.assertEquals("AES", key256.getDecryptedKey().getAlgorithm());
// now decrypt the key again
decryptKey = memoryKeystore.decryptLocalKey(metadata256, key256.getEncryptedKey());
Assert.assertEquals(stringify(key256.getDecryptedKey().getEncoded()),
stringify(decryptKey.getEncoded()));
}
@Test
public void testRollNewVersion() throws IOException {
Assert.assertEquals(0,
memoryKeystore.getCurrentKeyVersion("key128").getVersion());
memoryKeystore.addKey("key128", 1, EncryptionAlgorithm.AES_CTR_128, "NewSecret".getBytes(StandardCharsets.UTF_8));
Assert.assertEquals(1,
memoryKeystore.getCurrentKeyVersion("key128").getVersion());
}
@Test
public void testDuplicateKeyNames() {
try {
memoryKeystore.addKey("key128", 0, EncryptionAlgorithm.AES_CTR_128,
"exception".getBytes(StandardCharsets.UTF_8));
Assert.fail("Keys with same name cannot be added.");
} catch (IOException e) {
Assert.assertTrue(e.toString().contains("equal or higher version"));
}
}
/**
* This will test:
* 1. Scenario where key with smaller version then existing should not be allowed
* 2. Test multiple versions of the key
* 3. Test get current version
* 4. Ensure the different versions of the key have different material.
*/
@Test
public void testMultipleVersion() throws IOException {
Assert.assertEquals(0,
memoryKeystore.getCurrentKeyVersion("key256").getVersion());
memoryKeystore.addKey("key256", 1, EncryptionAlgorithm.AES_CTR_256,
"NewSecret".getBytes(StandardCharsets.UTF_8));
Assert.assertEquals(1,
memoryKeystore.getCurrentKeyVersion("key256").getVersion());
try {
memoryKeystore.addKey("key256", 1, EncryptionAlgorithm.AES_CTR_256,
"BadSecret".getBytes(StandardCharsets.UTF_8));
Assert.fail("Keys with smaller version should not be added.");
} catch (final IOException e) {
Assert.assertTrue(e.toString().contains("equal or higher version"));
}
memoryKeystore.addKey("key256", 2, EncryptionAlgorithm.AES_CTR_256,
"NewerSecret".getBytes(StandardCharsets.UTF_8));
Assert.assertEquals(2,
memoryKeystore.getCurrentKeyVersion("key256").getVersion());
// make sure that all 3 versions of key256 exist and have different secrets
Key key0 = memoryKeystore.decryptLocalKey(
new HadoopShims.KeyMetadata("key256", 0, EncryptionAlgorithm.AES_CTR_256),
new byte[16]);
Key key1 = memoryKeystore.decryptLocalKey(
new HadoopShims.KeyMetadata("key256", 1, EncryptionAlgorithm.AES_CTR_256),
new byte[16]);
Key key2 = memoryKeystore.decryptLocalKey(
new HadoopShims.KeyMetadata("key256", 2, EncryptionAlgorithm.AES_CTR_256),
new byte[16]);
Assert.assertNotEquals(new BytesWritable(key0.getEncoded()).toString(),
new BytesWritable(key1.getEncoded()).toString());
Assert.assertNotEquals(new BytesWritable(key1.getEncoded()).toString(),
new BytesWritable(key2.getEncoded()).toString());
}
}