Shim implementation for ORC's KeyProvider API that uses Hadoop's KeyProvider API and implementations. Most users use a Hadoop or Ranger KMS and thus should use this default implementation. The main two methods of ORC's KeyProvider are createLocalKey and decryptLocalKey. These are very similar to
| 81 | * to either take the random key or pass it back. |
| 82 | */ |
| 83 | class KeyProviderImpl implements KeyProvider { |
| 84 | private final org.apache.hadoop.crypto.key.KeyProvider provider; |
| 85 | private final Random random; |
| 86 | |
| 87 | KeyProviderImpl(org.apache.hadoop.crypto.key.KeyProvider provider, |
| 88 | Random random) { |
| 89 | this.provider = provider; |
| 90 | this.random = random; |
| 91 | } |
| 92 | |
| 93 | @Override |
| 94 | public List<String> getKeyNames() throws IOException { |
| 95 | return provider.getKeys(); |
| 96 | } |
| 97 | |
| 98 | @Override |
| 99 | public HadoopShims.KeyMetadata getCurrentKeyVersion(String keyName) throws IOException { |
| 100 | org.apache.hadoop.crypto.key.KeyProvider.Metadata meta = |
| 101 | provider.getMetadata(keyName); |
| 102 | return new HadoopShims.KeyMetadata(keyName, meta.getVersions() - 1, |
| 103 | HadoopShimsCurrent.findAlgorithm(meta)); |
| 104 | } |
| 105 | |
| 106 | /** |
| 107 | * The Ranger/Hadoop KMS mangles the IV by bit flipping it in a misguided |
| 108 | * attempt to improve security. By bit flipping it here, we undo the |
| 109 | * silliness so that we get |
| 110 | * |
| 111 | * @param input the input array to copy from |
| 112 | * @param output the output array to write to |
| 113 | */ |
| 114 | private static void unmangleIv(byte[] input, byte[] output) { |
| 115 | for (int i = 0; i < output.length && i < input.length; ++i) { |
| 116 | output[i] = (byte) (0xff ^ input[i]); |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | @Override |
| 121 | public LocalKey createLocalKey(HadoopShims.KeyMetadata key) throws IOException { |
| 122 | EncryptionAlgorithm algorithm = key.getAlgorithm(); |
| 123 | byte[] encryptedKey = new byte[algorithm.keyLength()]; |
| 124 | random.nextBytes(encryptedKey); |
| 125 | byte[] iv = new byte[algorithm.getIvLength()]; |
| 126 | unmangleIv(encryptedKey, iv); |
| 127 | EncryptedKeyVersion param = EncryptedKeyVersion.createForDecryption( |
| 128 | key.getKeyName(), HadoopShimsCurrent.buildKeyVersionName(key), iv, encryptedKey); |
| 129 | try { |
| 130 | KeyProviderCryptoExtension.KeyVersion decryptedKey; |
| 131 | if (provider instanceof KeyProviderCryptoExtension) { |
| 132 | decryptedKey = ((KeyProviderCryptoExtension) provider).decryptEncryptedKey(param); |
| 133 | } else if (provider instanceof CryptoExtension) { |
| 134 | decryptedKey = ((CryptoExtension) provider).decryptEncryptedKey(param); |
| 135 | } else { |
| 136 | throw new UnsupportedOperationException( |
| 137 | provider.getClass().getCanonicalName() + " is not supported."); |
| 138 | } |
| 139 | return new LocalKey(algorithm, decryptedKey.getMaterial(), |
| 140 | encryptedKey); |
nothing calls this directly
no outgoing calls
no test coverage detected