如何在Java中使用密钥库来存储私钥?

如何在Java中使用密钥库来存储私钥?,java,keystore,Java,Keystore,我使用了KeyPairGenerator来生成RSA密钥对。如果我没有错的话,密钥库只用于存储证书而不是密钥。如何在计算机上正确存储私钥 或 或 这是最有希望的 或 不可能在不受信任的环境中保护密钥。你可以混淆你的代码,你可以从任意变量中创建一个键,无论什么。最后,假设您使用标准的javax.crypto库,您必须调用Mac.getInstance(),稍后您将在该实例上调用init()。想要你钥匙的人会得到的 然而,我认为解决方案是将关键与环境联系起来,而不是与程序联系起来。签名意味着数

我使用了
KeyPairGenerator
来生成RSA密钥对。如果我没有错的话,密钥库只用于存储证书而不是密钥。如何在计算机上正确存储私钥

这是最有希望的

不可能在不受信任的环境中保护密钥。你可以混淆你的代码,你可以从任意变量中创建一个键,无论什么。最后,假设您使用标准的javax.crypto库,您必须调用Mac.getInstance(),稍后您将在该实例上调用init()。想要你钥匙的人会得到的


然而,我认为解决方案是将关键与环境联系起来,而不是与程序联系起来。签名意味着数据来源于已知来源,并且自该来源提供数据以来未被篡改。目前,您试图说“保证我的程序生成数据”。相反,将您的要求更改为“保证我的程序的特定用户生成数据。”然后,负责保管其密钥的责任转移给该用户。

根据私钥的格式,您可能需要将其转换为java keytool可以使用的格式

但是,如果它是在一个键工具支持的格式,你应该可以只导入它使用键工具。 更多信息,请访问:


注意:此代码仅用于演示目的。私钥在磁盘上存储时必须加密。不要按原样使用它

您可以这样做:

 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
 kpg.initialize(2048);

 KeyPair kp = kpg.genKeyPair();

 KeyFactory fact = KeyFactory.getInstance("RSA");

 RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(),
        RSAPublicKeySpec.class);
 saveToFile(PUBLIC_KEY_FILE, 
        pub.getModulus(), pub.getPublicExponent());

 RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(),
        RSAPrivateKeySpec.class);
 saveToFile(PRIVATE_KEY_FILE, 
         priv.getModulus(), priv.getPrivateExponent());
保存功能:

private static void saveToFile(String fileName,
                               BigInteger mod, BigInteger exp) 
    throws SomeException {
    ObjectOutputStream oout = new ObjectOutputStream(
            new BufferedOutputStream(new FileOutputStream(fileName)));
    try {
        oout.writeObject(mod);
        oout.writeObject(exp);
    } catch (Exception e) {
        throw new SomeException(e);
    } finally {
        oout.close();
    }
}
并以同样的方式阅读:

private static PublicKey readPublicKey() throws SomeException {
    InputStream in = new FileInputStream(PUBLIC_KEY_FILE);
    ObjectInputStream oin =
            new ObjectInputStream(new BufferedInputStream(in));
    try {
        BigInteger m = (BigInteger) oin.readObject();
        BigInteger e = (BigInteger) oin.readObject();
        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
        KeyFactory fact = KeyFactory.getInstance("RSA");
        PublicKey pubKey = fact.generatePublic(keySpec);
        return pubKey;
    } catch (Exception e) {
        throw new SomeException(e);
    } finally {
        oin.close();
    }
}

读取私钥与此类似。

此代码块将在AndroidKeyStore上生成并存储密钥对。(注:例外捕获省略)


@segfault,还请记住,您需要
将此添加到
AndroidManifest.xml
将私钥存储在可通过其他应用访问的存储器中是否安全?(如果我错了,请纠正我,但这里就是这么做的。)由您在操作系统级别设置文件权限(例如,应用程序的专用用户等)。值得注意的是,它超出了这个答案的范围。所以你不使用
keystore
这意味着你没有回答这个问题这是我见过的最危险的安全/代码黑客之一。你甚至不建议保护私钥。好的,这应该只适用于Android。Java怎么样?KeyPairGeneratorSpec已被弃用。请参阅:
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);

String alias = "my_key"; // replace as required or get it as a function argument

int nBefore = keyStore.size(); // debugging variable to help convince yourself this works

// Create the keys if necessary
if (!keyStore.containsAlias(alias)) {

    Calendar notBefore = Calendar.getInstance();
    Calendar notAfter = Calendar.getInstance();
    notAfter.add(Calendar.YEAR, 1);
    KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this)
                    .setAlias(alias)
                    .setKeyType("RSA")
                    .setKeySize(2048)
                    .setSubject(new X500Principal("CN=test"))
                    .setSerialNumber(BigInteger.ONE)
                    .setStartDate(notBefore.getTime())
                    .setEndDate(notAfter.getTime())
                    .build();
    KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
    generator.initialize(spec);

    KeyPair keyPair = generator.generateKeyPair();
}
int nAfter = keyStore.size();
Log.v(TAG, "Before = " + nBefore + " After = " + nAfter);

// Retrieve the keys
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey();
RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey();

Log.v(TAG, "private key = " + privateKey.toString());
Log.v(TAG, "public key = " + publicKey.toString());