hadoop KeyProviderCryptoExtension 源码

  • 2022-10-20
  • 浏览 (405)

haddop KeyProviderCryptoExtension 代码

文件路径:/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/crypto/key/KeyProviderCryptoExtension.java

/**
 * 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
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.hadoop.crypto.key;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.util.List;
import java.util.ListIterator;

import org.apache.hadoop.util.Preconditions;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.crypto.CryptoCodec;
import org.apache.hadoop.crypto.Decryptor;
import org.apache.hadoop.crypto.Encryptor;

/**
 * A KeyProvider with Cryptographic Extensions specifically for generating
 * and decrypting encrypted encryption keys.
 * 
 */
@InterfaceAudience.Private
public class KeyProviderCryptoExtension extends
    KeyProviderExtension<KeyProviderCryptoExtension.CryptoExtension> {

  /**
   * Designates an encrypted encryption key, or EEK.
   */
  public static final String EEK = "EEK";
  /**
   * Designates a decrypted encrypted encryption key, that is, an encryption key
   * (EK).
   */
  public static final String EK = "EK";

  /**
   * An encrypted encryption key (EEK) and related information. An EEK must be
   * decrypted using the key's encryption key before it can be used.
   */
  public static class EncryptedKeyVersion {
    private String encryptionKeyName;
    private String encryptionKeyVersionName;
    private byte[] encryptedKeyIv;
    private KeyVersion encryptedKeyVersion;

    /**
     * Create a new EncryptedKeyVersion.
     *
     * @param keyName                  Name of the encryption key used to
     *                                 encrypt the encrypted key.
     * @param encryptionKeyVersionName Version name of the encryption key used
     *                                 to encrypt the encrypted key.
     * @param encryptedKeyIv           Initialization vector of the encrypted
     *                                 key. The IV of the encryption key used to
     *                                 encrypt the encrypted key is derived from
     *                                 this IV.
     * @param encryptedKeyVersion      The encrypted encryption key version.
     */
    protected EncryptedKeyVersion(String keyName,
        String encryptionKeyVersionName, byte[] encryptedKeyIv,
        KeyVersion encryptedKeyVersion) {
      this.encryptionKeyName = keyName == null ? null : keyName.intern();
      this.encryptionKeyVersionName = encryptionKeyVersionName == null ?
          null : encryptionKeyVersionName.intern();
      this.encryptedKeyIv = encryptedKeyIv;
      this.encryptedKeyVersion = encryptedKeyVersion;
    }

    /**
     * Factory method to create a new EncryptedKeyVersion that can then be
     * passed into {@link #decryptEncryptedKey}. Note that the fields of the
     * returned EncryptedKeyVersion will only partially be populated; it is not
     * necessarily suitable for operations besides decryption.
     *
     * @param keyName Key name of the encryption key use to encrypt the
     *                encrypted key.
     * @param encryptionKeyVersionName Version name of the encryption key used
     *                                 to encrypt the encrypted key.
     * @param encryptedKeyIv           Initialization vector of the encrypted
     *                                 key. The IV of the encryption key used to
     *                                 encrypt the encrypted key is derived from
     *                                 this IV.
     * @param encryptedKeyMaterial     Key material of the encrypted key.
     * @return EncryptedKeyVersion suitable for decryption.
     */
    public static EncryptedKeyVersion createForDecryption(String keyName,
        String encryptionKeyVersionName, byte[] encryptedKeyIv,
        byte[] encryptedKeyMaterial) {
      KeyVersion encryptedKeyVersion = new KeyVersion(null, EEK,
          encryptedKeyMaterial);
      return new EncryptedKeyVersion(keyName, encryptionKeyVersionName,
          encryptedKeyIv, encryptedKeyVersion);
    }

    /**
     * @return Name of the encryption key used to encrypt the encrypted key.
     */
    public String getEncryptionKeyName() {
      return encryptionKeyName;
    }

    /**
     * @return Version name of the encryption key used to encrypt the encrypted
     * key.
     */
    public String getEncryptionKeyVersionName() {
      return encryptionKeyVersionName;
    }

    /**
     * @return Initialization vector of the encrypted key. The IV of the
     * encryption key used to encrypt the encrypted key is derived from this
     * IV.
     */
    public byte[] getEncryptedKeyIv() {
      return encryptedKeyIv;
    }

    /**
     * @return The encrypted encryption key version.
     */
    public KeyVersion getEncryptedKeyVersion() {
      return encryptedKeyVersion;
    }

    /**
     * Derive the initialization vector (IV) for the encryption key from the IV
     * of the encrypted key. This derived IV is used with the encryption key to
     * decrypt the encrypted key.
     * <p>
     * The alternative to this is using the same IV for both the encryption key
     * and the encrypted key. Even a simple symmetric transformation like this
     * improves security by avoiding IV re-use. IVs will also be fairly unique
     * among different EEKs.
     *
     * @param encryptedKeyIV of the encrypted key (i.e. {@link
     * #getEncryptedKeyIv()})
     * @return IV for the encryption key
     */
    protected static byte[] deriveIV(byte[] encryptedKeyIV) {
      byte[] rIv = new byte[encryptedKeyIV.length];
      // Do a simple XOR transformation to flip all the bits
      for (int i = 0; i < encryptedKeyIV.length; i++) {
        rIv[i] = (byte) (encryptedKeyIV[i] ^ 0xff);
      }
      return rIv;
    }
  }

  /**
   * CryptoExtension is a type of Extension that exposes methods to generate
   * EncryptedKeys and to decrypt the same.
   */
  public interface CryptoExtension extends KeyProviderExtension.Extension {

    /**
     * Calls to this method allows the underlying KeyProvider to warm-up any
     * implementation specific caches used to store the Encrypted Keys.
     * @param keyNames Array of Key Names
     * @throws IOException thrown if the key material could not be encrypted.
     */
    public void warmUpEncryptedKeys(String... keyNames)
        throws IOException;

    /**
     * Drains the Queue for the provided key.
     *
     * @param keyName the key to drain the Queue for
     */
    public void drain(String keyName);

    /**
     * Generates a key material and encrypts it using the given key name.
     * The generated key material is of the same
     * length as the <code>KeyVersion</code> material of the latest key version
     * of the key and is encrypted using the same cipher.
     * <p>
     * NOTE: The generated key is not stored by the <code>KeyProvider</code>
     * 
     * @param encryptionKeyName
     *          The latest KeyVersion of this key's material will be encrypted.
     * @return EncryptedKeyVersion with the generated key material, the version
     *         name is 'EEK' (for Encrypted Encryption Key)
     * @throws IOException
     *           thrown if the key material could not be generated
     * @throws GeneralSecurityException
     *           thrown if the key material could not be encrypted because of a
     *           cryptographic issue.
     */
    public EncryptedKeyVersion generateEncryptedKey(
        String encryptionKeyName) throws IOException,
        GeneralSecurityException;

    /**
     * Decrypts an encrypted byte[] key material using the given key version
     * name and initialization vector.
     * 
     * @param encryptedKeyVersion
     *          contains keyVersionName and IV to decrypt the encrypted key
     *          material
     * @return a KeyVersion with the decrypted key material, the version name is
     *         'EK' (For Encryption Key)
     * @throws IOException
     *           thrown if the key material could not be decrypted
     * @throws GeneralSecurityException
     *           thrown if the key material could not be decrypted because of a
     *           cryptographic issue.
     */
    public KeyVersion decryptEncryptedKey(
        EncryptedKeyVersion encryptedKeyVersion) throws IOException,
        GeneralSecurityException;

    /**
     * Re-encrypts an encrypted key version, using its initialization vector
     * and key material, but with the latest key version name of its key name
     * in the key provider.
     * <p>
     * If the latest key version name in the provider is the
     * same as the one encrypted the passed-in encrypted key version, the same
     * encrypted key version is returned.
     * <p>
     * NOTE: The generated key is not stored by the <code>KeyProvider</code>
     *
     * @param  ekv The EncryptedKeyVersion containing keyVersionName and IV.
     * @return     The re-encrypted EncryptedKeyVersion.
     * @throws IOException If the key material could not be re-encrypted.
     * @throws GeneralSecurityException If the key material could not be
     *                            re-encrypted because of a cryptographic issue.
     */
    EncryptedKeyVersion reencryptEncryptedKey(EncryptedKeyVersion ekv)
        throws IOException, GeneralSecurityException;

    /**
     * Batched version of {@link #reencryptEncryptedKey(EncryptedKeyVersion)}.
     * <p>
     * For each encrypted key version, re-encrypts an encrypted key version,
     * using its initialization vector and key material, but with the latest
     * key version name of its key name. If the latest key version name in the
     * provider is the same as the one encrypted the passed-in encrypted key
     * version, the same encrypted key version is returned.
     * <p>
     * NOTE: The generated key is not stored by the <code>KeyProvider</code>
     *
     * @param  ekvs List containing the EncryptedKeyVersion's
     * @throws IOException If any EncryptedKeyVersion could not be re-encrypted
     * @throws GeneralSecurityException If any EncryptedKeyVersion could not be
     *                            re-encrypted because of a cryptographic issue.
     */
    void reencryptEncryptedKeys(List<EncryptedKeyVersion> ekvs)
        throws IOException, GeneralSecurityException;
  }

  private static class DefaultCryptoExtension implements CryptoExtension {

    private final KeyProvider keyProvider;
    private static final ThreadLocal<SecureRandom> RANDOM = 
        new ThreadLocal<SecureRandom>() {
      @Override
      protected SecureRandom initialValue() {
        return new SecureRandom();
      }
    };

    private DefaultCryptoExtension(KeyProvider keyProvider) {
      this.keyProvider = keyProvider;
    }

    @Override
    public EncryptedKeyVersion generateEncryptedKey(String encryptionKeyName)
        throws IOException, GeneralSecurityException {
      // Fetch the encryption key
      KeyVersion encryptionKey = keyProvider.getCurrentKey(encryptionKeyName);
      Preconditions.checkNotNull(encryptionKey,
          "No KeyVersion exists for key '%s' ", encryptionKeyName);
      // Generate random bytes for new key and IV

      CryptoCodec cc = CryptoCodec.getInstance(keyProvider.getConf());
      try {
        final byte[] newKey = new byte[encryptionKey.getMaterial().length];
        cc.generateSecureRandom(newKey);
        final byte[] iv = new byte[cc.getCipherSuite().getAlgorithmBlockSize()];
        cc.generateSecureRandom(iv);
        Encryptor encryptor = cc.createEncryptor();
        return generateEncryptedKey(encryptor, encryptionKey, newKey, iv);
      } finally {
        cc.close();
      }
    }

    private EncryptedKeyVersion generateEncryptedKey(final Encryptor encryptor,
        final KeyVersion encryptionKey, final byte[] key, final byte[] iv)
        throws IOException, GeneralSecurityException {
      // Encryption key IV is derived from new key's IV
      final byte[] encryptionIV = EncryptedKeyVersion.deriveIV(iv);
      encryptor.init(encryptionKey.getMaterial(), encryptionIV);
      final int keyLen = key.length;
      ByteBuffer bbIn = ByteBuffer.allocateDirect(keyLen);
      ByteBuffer bbOut = ByteBuffer.allocateDirect(keyLen);
      bbIn.put(key);
      bbIn.flip();
      encryptor.encrypt(bbIn, bbOut);
      bbOut.flip();
      byte[] encryptedKey = new byte[keyLen];
      bbOut.get(encryptedKey);
      return new EncryptedKeyVersion(encryptionKey.getName(),
          encryptionKey.getVersionName(), iv,
          new KeyVersion(encryptionKey.getName(), EEK, encryptedKey));
    }

    @Override
    public EncryptedKeyVersion reencryptEncryptedKey(EncryptedKeyVersion ekv)
        throws IOException, GeneralSecurityException {
      final String ekName = ekv.getEncryptionKeyName();
      final KeyVersion ekNow = keyProvider.getCurrentKey(ekName);
      Preconditions
          .checkNotNull(ekNow, "KeyVersion name '%s' does not exist", ekName);
      Preconditions.checkArgument(ekv.getEncryptedKeyVersion().getVersionName()
              .equals(KeyProviderCryptoExtension.EEK),
          "encryptedKey version name must be '%s', but found '%s'",
          KeyProviderCryptoExtension.EEK,
          ekv.getEncryptedKeyVersion().getVersionName());

      if (ekv.getEncryptedKeyVersion().equals(ekNow)) {
        // no-op if same key version
        return ekv;
      }

      final KeyVersion dek = decryptEncryptedKey(ekv);
      final CryptoCodec cc = CryptoCodec.getInstance(keyProvider.getConf());
      try {
        final Encryptor encryptor = cc.createEncryptor();
        return generateEncryptedKey(encryptor, ekNow, dek.getMaterial(),
            ekv.getEncryptedKeyIv());
      } finally {
        cc.close();
      }
    }

    @Override
    public void reencryptEncryptedKeys(List<EncryptedKeyVersion> ekvs)
        throws IOException, GeneralSecurityException {
      Preconditions.checkNotNull(ekvs, "Input list is null");
      KeyVersion ekNow = null;
      Decryptor decryptor = null;
      Encryptor encryptor = null;
      try (CryptoCodec cc = CryptoCodec.getInstance(keyProvider.getConf())) {
        decryptor = cc.createDecryptor();
        encryptor = cc.createEncryptor();
        ListIterator<EncryptedKeyVersion> iter = ekvs.listIterator();
        while (iter.hasNext()) {
          final EncryptedKeyVersion ekv = iter.next();
          Preconditions.checkNotNull(ekv, "EncryptedKeyVersion is null");
          final String ekName = ekv.getEncryptionKeyName();
          Preconditions.checkNotNull(ekName, "Key name is null");
          Preconditions.checkNotNull(ekv.getEncryptedKeyVersion(),
              "EncryptedKeyVersion is null");
          Preconditions.checkArgument(
              ekv.getEncryptedKeyVersion().getVersionName()
                  .equals(KeyProviderCryptoExtension.EEK),
              "encryptedKey version name must be '%s', but found '%s'",
              KeyProviderCryptoExtension.EEK,
              ekv.getEncryptedKeyVersion().getVersionName());

          if (ekNow == null) {
            ekNow = keyProvider.getCurrentKey(ekName);
            Preconditions
                .checkNotNull(ekNow, "Key name '%s' does not exist", ekName);
          } else {
            Preconditions.checkArgument(ekNow.getName().equals(ekName),
                "All keys must have the same key name. Expected '%s' "
                    + "but found '%s'", ekNow.getName(), ekName);
          }

          final String encryptionKeyVersionName =
              ekv.getEncryptionKeyVersionName();
          final KeyVersion encryptionKey =
              keyProvider.getKeyVersion(encryptionKeyVersionName);
          Preconditions.checkNotNull(encryptionKey,
              "KeyVersion name '%s' does not exist", encryptionKeyVersionName);
          if (encryptionKey.equals(ekNow)) {
            // no-op if same key version
            continue;
          }

          final KeyVersion ek =
              decryptEncryptedKey(decryptor, encryptionKey, ekv);
          iter.set(generateEncryptedKey(encryptor, ekNow, ek.getMaterial(),
              ekv.getEncryptedKeyIv()));
        }
      }
    }

    private KeyVersion decryptEncryptedKey(final Decryptor decryptor,
        final KeyVersion encryptionKey,
        final EncryptedKeyVersion encryptedKeyVersion)
        throws IOException, GeneralSecurityException {
      // Encryption key IV is determined from encrypted key's IV
      final byte[] encryptionIV =
          EncryptedKeyVersion.deriveIV(encryptedKeyVersion.getEncryptedKeyIv());

      decryptor.init(encryptionKey.getMaterial(), encryptionIV);
      final KeyVersion encryptedKV =
          encryptedKeyVersion.getEncryptedKeyVersion();
      int keyLen = encryptedKV.getMaterial().length;
      ByteBuffer bbIn = ByteBuffer.allocateDirect(keyLen);
      ByteBuffer bbOut = ByteBuffer.allocateDirect(keyLen);
      bbIn.put(encryptedKV.getMaterial());
      bbIn.flip();
      decryptor.decrypt(bbIn, bbOut);
      bbOut.flip();
      byte[] decryptedKey = new byte[keyLen];
      bbOut.get(decryptedKey);
      return new KeyVersion(encryptionKey.getName(), EK, decryptedKey);
    }

    @Override
    public KeyVersion decryptEncryptedKey(
        EncryptedKeyVersion encryptedKeyVersion)
        throws IOException, GeneralSecurityException {
      // Fetch the encryption key material
      final String encryptionKeyVersionName =
          encryptedKeyVersion.getEncryptionKeyVersionName();
      final KeyVersion encryptionKey =
          keyProvider.getKeyVersion(encryptionKeyVersionName);
      Preconditions
          .checkNotNull(encryptionKey, "KeyVersion name '%s' does not exist",
              encryptionKeyVersionName);
      Preconditions.checkArgument(
          encryptedKeyVersion.getEncryptedKeyVersion().getVersionName()
              .equals(KeyProviderCryptoExtension.EEK),
          "encryptedKey version name must be '%s', but found '%s'",
          KeyProviderCryptoExtension.EEK,
          encryptedKeyVersion.getEncryptedKeyVersion().getVersionName());

      try (CryptoCodec cc = CryptoCodec.getInstance(keyProvider.getConf())) {
        final Decryptor decryptor = cc.createDecryptor();
        return decryptEncryptedKey(decryptor, encryptionKey,
            encryptedKeyVersion);
      }
    }

    @Override
    public void warmUpEncryptedKeys(String... keyNames)
        throws IOException {
      // NO-OP since the default version does not cache any keys
    }

    @Override
    public void drain(String keyName) {
      // NO-OP since the default version does not cache any keys
    }
  }

  /**
   * This constructor is to be used by sub classes that provide
   * delegating/proxying functionality to the {@link KeyProviderCryptoExtension}
   *
   * @param keyProvider key provider.
   * @param extension crypto extension.
   */
  protected KeyProviderCryptoExtension(KeyProvider keyProvider,
      CryptoExtension extension) {
    super(keyProvider, extension);
  }

  /**
   * Notifies the Underlying CryptoExtension implementation to warm up any
   * implementation specific caches for the specified KeyVersions
   * @param keyNames Arrays of key Names
   * @throws IOException raised on errors performing I/O.
   */
  public void warmUpEncryptedKeys(String... keyNames)
      throws IOException {
    getExtension().warmUpEncryptedKeys(keyNames);
  }

  /**
   * Generates a key material and encrypts it using the given key version name
   * and initialization vector. The generated key material is of the same
   * length as the <code>KeyVersion</code> material and is encrypted using the
   * same cipher.
   * <p>
   * NOTE: The generated key is not stored by the <code>KeyProvider</code>
   *
   * @param encryptionKeyName The latest KeyVersion of this key's material will
   * be encrypted.
   * @return EncryptedKeyVersion with the generated key material, the version
   * name is 'EEK' (for Encrypted Encryption Key)
   * @throws IOException thrown if the key material could not be generated
   * @throws GeneralSecurityException thrown if the key material could not be 
   * encrypted because of a cryptographic issue.
   */
  public EncryptedKeyVersion generateEncryptedKey(String encryptionKeyName)
      throws IOException,
                                           GeneralSecurityException {
    return getExtension().generateEncryptedKey(encryptionKeyName);
  }

  /**
   * Decrypts an encrypted byte[] key material using the given a key version
   * name and initialization vector.
   *
   * @param encryptedKey contains keyVersionName and IV to decrypt the encrypted 
   * key material
   * @return a KeyVersion with the decrypted key material, the version name is
   * 'EK' (For Encryption Key)
   * @throws IOException thrown if the key material could not be decrypted
   * @throws GeneralSecurityException thrown if the key material could not be 
   * decrypted because of a cryptographic issue.
   */
  public KeyVersion decryptEncryptedKey(EncryptedKeyVersion encryptedKey) 
      throws IOException, GeneralSecurityException {
    return getExtension().decryptEncryptedKey(encryptedKey);
  }

  /**
   * Re-encrypts an encrypted key version, using its initialization vector
   * and key material, but with the latest key version name of its key name
   * in the key provider.
   * <p>
   * If the latest key version name in the provider is the
   * same as the one encrypted the passed-in encrypted key version, the same
   * encrypted key version is returned.
   * <p>
   * NOTE: The generated key is not stored by the <code>KeyProvider</code>
   *
   * @param  ekv The EncryptedKeyVersion containing keyVersionName and IV.
   * @return     The re-encrypted EncryptedKeyVersion.
   * @throws IOException If the key material could not be re-encrypted
   * @throws GeneralSecurityException If the key material could not be
   *                            re-encrypted because of a cryptographic issue.
   */
  public EncryptedKeyVersion reencryptEncryptedKey(EncryptedKeyVersion ekv)
      throws IOException, GeneralSecurityException {
    return getExtension().reencryptEncryptedKey(ekv);
  }

  /**
   * Calls {@link CryptoExtension#drain(String)} for the given key name on the
   * underlying {@link CryptoExtension}.
   *
   * @param keyName key name.
   */
  public void drain(String keyName) {
    getExtension().drain(keyName);
  }

  /**
   * Batched version of {@link #reencryptEncryptedKey(EncryptedKeyVersion)}.
   * <p>
   * For each encrypted key version, re-encrypts an encrypted key version,
   * using its initialization vector and key material, but with the latest
   * key version name of its key name. If the latest key version name in the
   * provider is the same as the one encrypted the passed-in encrypted key
   * version, the same encrypted key version is returned.
   * <p>
   * NOTE: The generated key is not stored by the <code>KeyProvider</code>
   *
   * @param  ekvs List containing the EncryptedKeyVersion's
   * @throws IOException If any EncryptedKeyVersion could not be re-encrypted
   * @throws GeneralSecurityException If any EncryptedKeyVersion could not be
   *                            re-encrypted because of a cryptographic issue.
   */
  public void reencryptEncryptedKeys(List<EncryptedKeyVersion> ekvs)
      throws IOException, GeneralSecurityException {
    getExtension().reencryptEncryptedKeys(ekvs);
  }

  /**
   * Creates a <code>KeyProviderCryptoExtension</code> using a given
   * {@link KeyProvider}.
   * <p>
   * If the given <code>KeyProvider</code> implements the
   * {@link CryptoExtension} interface the <code>KeyProvider</code> itself
   * will provide the extension functionality.
   * If the given <code>KeyProvider</code> implements the
   * {@link KeyProviderExtension} interface and the KeyProvider being
   * extended by the <code>KeyProvider</code> implements the
   * {@link CryptoExtension} interface, the KeyProvider being extended will
   * provide the extension functionality. Otherwise, a default extension
   * implementation will be used.
   *
   * @param keyProvider <code>KeyProvider</code> to use to create the
   * <code>KeyProviderCryptoExtension</code> extension.
   * @return a <code>KeyProviderCryptoExtension</code> instance using the
   * given <code>KeyProvider</code>.
   */
  public static KeyProviderCryptoExtension createKeyProviderCryptoExtension(
      KeyProvider keyProvider) {
    CryptoExtension cryptoExtension = null;
    if (keyProvider instanceof CryptoExtension) {
      cryptoExtension = (CryptoExtension) keyProvider;
    } else if (keyProvider instanceof KeyProviderExtension &&
            ((KeyProviderExtension)keyProvider).getKeyProvider() instanceof
                    KeyProviderCryptoExtension.CryptoExtension) {
      KeyProviderExtension keyProviderExtension =
              (KeyProviderExtension)keyProvider;
      cryptoExtension =
              (CryptoExtension)keyProviderExtension.getKeyProvider();
    } else {
      cryptoExtension = new DefaultCryptoExtension(keyProvider);
    }
    return new KeyProviderCryptoExtension(keyProvider, cryptoExtension);
  }

  @Override
  public void close() throws IOException {
    KeyProvider provider = getKeyProvider();
    if (provider != null && provider != this) {
      provider.close();
    }
  }

}

相关信息

hadoop 源码目录

相关文章

hadoop CachingKeyProvider 源码

hadoop JavaKeyStoreProvider 源码

hadoop KeyProvider 源码

hadoop KeyProviderDelegationTokenExtension 源码

hadoop KeyProviderExtension 源码

hadoop KeyProviderFactory 源码

hadoop KeyProviderTokenIssuer 源码

hadoop KeyShell 源码

hadoop UserProvider 源码

hadoop package-info 源码

0  赞