java.security.spec.InvalidKeySpecException:java.lang.NoSuchMethodException:

问题描述 投票:0回答:1

我正在开发一个android应用程序,试图在该应用程序中使用secretkeyfactory设置并在Keystore文件中获取秘密值。我可以设置该值,但是当我尝试获取该值时,它将显示以下错误-java.security.spec.InvalidKeySpecException:

创建密钥存储文件的功能

private static KeyStore createKeyStore(String fileName, String pw) throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException {
    File file = new File(this.getFilesDir().getPath().toString() + filename);

    final KeyStore keyStore = KeyStore.getInstance("BKS");
    if (file.exists()) {
      keyStore.load(new FileInputStream(file), pw.toCharArray());
    } else {
      keyStore.load(null, null);
      keyStore.store(new FileOutputStream(this.getFilesDir().getPath().toString() + filename), pw.toCharArray());
    }

    return keyStore;
  }

获得价值的功能

public static String getKey(String key, String keystoreLocation, String keyStorePassword) throws Exception{
    KeyStore ks = KeyStore.getInstance("BKS");
    ks.load(null, keyStorePassword.toCharArray());
    KeyStore.PasswordProtection keyStorePP = new KeyStore.PasswordProtection(keyStorePassword.toCharArray());
    FileInputStream fIn = new FileInputStream(keystoreLocation);
    ks.load(fIn, keyStorePassword.toCharArray());
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEwithHmacSHA1");
    KeyStore.SecretKeyEntry ske =
      (KeyStore.SecretKeyEntry)ks.getEntry(key, keyStorePP);

    PBEKeySpec keySpec = (PBEKeySpec)factory.getKeySpec(
        ske.getSecretKey(),
        PBEKeySpec.class);

    char[] password = keySpec.getPassword();

    return new String(password);

  }

设置值的功能

public static void setKey(String key, String value, String keyStoreLocation, String keyStorePassword) throws Exception {

    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEwithHmacSHA1");
    SecretKey generatedSecret = factory.generateSecret(new PBEKeySpec(value.toCharArray()));

    KeyStore ks = KeyStore.getInstance("BKS");
    ks.load(null, keyStorePassword.toCharArray());
    KeyStore.PasswordProtection keyStorePP = new KeyStore.PasswordProtection(keyStorePassword.toCharArray());

    ks.setEntry(key, new KeyStore.SecretKeyEntry( generatedSecret), keyStorePP);

    FileOutputStream fos = new java.io.FileOutputStream(keyStoreLocation);
    ks.store(fos, keyStorePassword.toCharArray());
  }
}

错误:

java.security.spec.InvalidKeySpecException: java.lang.NoSuchMethodException:
at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseSecretKeyFactory.engineGetKeySpec(BaseSecretKeyFactory.java:73)

在getKey函数的这一行中发生错误

PBEKeySpec keySpec = (PBEKeySpec)factory.getKeySpec(
            ske.getSecretKey(),
            PBEKeySpec.class);
java android encryption keystore
1个回答
0
投票

((1)可以,但是不起作用:

SecretKey key = ske.getSecretKey();
SecretKeySpeckeySpec = (SecretKeySpec)factory.getKeySpec(ke.getSecretKey(),SecretKeySpec.class);

((2)code可以,但是会出现错误:java.lang.ClassCastException:无法将javax.crypto.spec.SecretKeySpec强制转换为javax.crypto.interfaces.PBEKey

PBEKey key = (PBEKey)ske.getSecretKey();
PBEKeySpec keySpec = (PBEKeySpec)factory.getKeySpec((PBEKey)ke.getSecretKey(),PBEKeySpec.class);

引起原因:

public class SecretKeySpec implements KeySpec, SecretKey
public class PBEKeySpec implements KeySpec

ske.getSecretKey()只是SecretKeySpec的一个实例

解决方案:(其他人的代码)

void implInit(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
    char[] passwdChars = null;
    salt = null;
    iCount = 0;
    if (key instanceof javax.crypto.interfaces.PBEKey) {
        javax.crypto.interfaces.PBEKey pbeKey = (javax.crypto.interfaces.PBEKey) key;
        passwdChars = pbeKey.getPassword();
        // maybe null if unspecified
        salt = pbeKey.getSalt();
        // maybe 0 if unspecified
        iCount = pbeKey.getIterationCount();
    } else if (key instanceof SecretKey) {
        byte[] passwdBytes = key.getEncoded();
        if ((passwdBytes == null) || !(key.getAlgorithm().regionMatches(true, 0, "PBE", 0, 3))) {
            throw new InvalidKeyException("Missing password");
        }
        passwdChars = new char[passwdBytes.length];
        for (int i = 0; i < passwdChars.length; i++) {
            passwdChars[i] = (char) (passwdBytes[i] & 0x7f);
        }
    } else {
        throw new InvalidKeyException("SecretKey of PBE type required");
    }
    if (((opmode == Cipher.DECRYPT_MODE) || (opmode == Cipher.UNWRAP_MODE)) && ((params == null) && ((salt == null) || (iCount == 0)))) {
        throw new InvalidAlgorithmParameterException("Parameters missing");
    }
    if (params == null) {
        // generate default for salt and iteration count if necessary
        if (salt == null) {
            salt = new byte[DEFAULT_SALT_LENGTH];
            if (random != null) {
                random.nextBytes(salt);
            } else {
                SunJCE.RANDOM.nextBytes(salt);
            }
        }
        if (iCount == 0)
            iCount = DEFAULT_COUNT;
    } else if (!(params instanceof PBEParameterSpec)) {
        throw new InvalidAlgorithmParameterException("PBEParameterSpec type required");
    } else {
        PBEParameterSpec pbeParams = (PBEParameterSpec) params;
        // make sure the parameter values are consistent
        if (salt != null) {
            if (!Arrays.equals(salt, pbeParams.getSalt())) {
                throw new InvalidAlgorithmParameterException("Inconsistent value of salt between key and params");
            }
        } else {
            salt = pbeParams.getSalt();
        }
        if (iCount != 0) {
            if (iCount != pbeParams.getIterationCount()) {
                throw new InvalidAlgorithmParameterException("Different iteration count between key and params");
            }
        } else {
            iCount = pbeParams.getIterationCount();
        }
    }
    // and openssl does.
    if (salt.length < 8) {
        throw new InvalidAlgorithmParameterException("Salt must be at least 8 bytes long");
    }
    if (iCount <= 0) {
        throw new InvalidAlgorithmParameterException("IterationCount must be a positive number");
    }
    byte[] derivedKey = derive(passwdChars, salt, iCount, keySize, CIPHER_KEY);
    SecretKey cipherKey = new SecretKeySpec(derivedKey, algo);
    byte[] derivedIv = derive(passwdChars, salt, iCount, 8, CIPHER_IV);
    IvParameterSpec ivSpec = new IvParameterSpec(derivedIv, 0, 8);
    // initialize the underlying cipher
    cipher.init(opmode, cipherKey, ivSpec, random);
}
© www.soinside.com 2019 - 2024. All rights reserved.