Android RSA Keypair Generation - 我应该使用标准Java/Bouncy Castle/Spongy Castle/JSch/Other吗?

2022-09-01 06:48:18

我已经四处寻找了大约一个星期+来实现我心目中的方法。我遇到(并阅读)了许多关于所有这些不同方法的文章,但我仍然感到困惑,所以我希望也许有人可以传播他们对这些主题的知识,这样我就可以更轻松地创建我追求的方法并在Android中实现它。

我的“追捧”方法:

  1. 必须生成 RSA 公钥和私钥
  2. 公众必须具有 PKCS#1 填充
  3. 必须是 RSA 2048
  4. 返回字节数组中的公钥

显然,你可以用四种方式去做:

  1. 标准爪哇
  2. 充气城堡
  3. 海绵城堡 (安卓友好?
  4. 断续器

由于我对安全和整个Java非常陌生,我想知道是否有人可以最终对这一切给出一个很好的明确解释。

以下是我试图在4种不同的编程方法中实现我追求的方法(如上所述)的方法。如果我不知道什么,那是因为我无法通过相应的文档弄清楚。请随时纠正我。

1. 标准 Java(不确定是否为 PKCS#1):

public byte[] returnPublicKeyInBytes() throws NoSuchAlgorithmException {
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(2048);
    KeyPair keyPair = kpg.genKeyPair();
    byte[] pri = keyPair.getPrivate().getEncoded();
    byte[] pub = keyPair.getPublic().getEncoded();
    return pub;
}

2.充气城堡(尚未功能=/想法?):

public byte[] returnPublicKeyInBytes() throws NoSuchAlgorithmException {
    RSAKeyPairGenerator r = new RSAKeyPairGenerator();
    r.init(new KeyGenerationParameters(new SecureRandom(),4096));
    AsymmetricCipherKeyPair keys = r.generateKeyPair();
    CipherParameters pri = keys.getPrivate();
    CipherParameters pub = keys.getPublic();
    byte[] pubbyte = pub.toString().getBytes();
    return pubbyte; //NOT WORKING
}

3.海绵城堡(没有启动它/与充气城堡相同?

4. JSch(非常功能失调/正在处理中)

public byte[] returnPublicKeyInBytes(JSch jSch) {
    try { 
        KeyPair keyPair = KeyPair.genKeyPair(jSch, KeyPair.RSA);
        ByteArrayOutputStream bs = new ByteArrayOutputStream(); 
        keyPair.writePrivateKey(bs); 
        jSch.addIdentity("Generated", bs.toByteArray(), keyPair.getPublicKeyBlob(), null);
        return keyPair.getPublicKeyBlob(); 
    } catch (JSchException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
    }
    return null;
}

我希望这能真正成为任何在Android中RSA密钥生成有问题的人(就像我和许多其他人一样)的资源。


我觉得Bouncy Castle关于它的API的信息很少,这使得初学者(像我一样)很难理解它。根据我的研究,人们使用Java中的Bouncy Castle而不是内置的安全提供程序,因为Bouncy Castle更加强大在Android中使用充气城堡是不希望的,因为它“附带了充气城堡的残缺版本”,这可能容易出错。海绵城堡只是充气城堡的重新包装

为此,我将提出最后一个问题,Android应该使用哪种方法?

更新

我希望以后有人能回答这个问题。至于我为解决我的问题所做的只是使用NDK。


答案 1

这很复杂,但我会尽力解释。我想我会从Java开始。我的讨论是针对Java 6的,我不确定Java 7中发生了什么变化。

Java的内置加密可以通过Java Cryptography Extension(JCE)获得。此扩展包含两个部分,即应用程序 API 和服务提供商 API。应用程序 API 是您与之交互的部分。您可以使用各种加密类的工厂方法。对于普通程序员来说,服务提供商方面更加混乱。他们不关心加密是如何实现的,他们只是想要一些有效的东西。但是在引擎盖下,有加密提供程序类可以执行实际工作。如果您查看 参数,您会发现您可以根据需要指定提供程序。你为什么会想要?也许您已经为 RSA 的优化商业实现支付了 $$$,因此您希望使用该实施。也许一个提供商具有你的应用所需的 FIPS 证书或其他一些认证。然后,您将指定该提供程序。Sun/Oracle 在发布其 Java 环境时附带了多个提供程序,这些提供程序共同构成了为其 Java 环境设置的默认提供程序集。不要太仔细地看它们,因为它们是重叠的,因此由于历史文物而有些混乱。基本上,当使用Oracle Java时,你要求一些加密,比如通过,你将从这些提供商之一获得一个合适的类实例。getInstance()getInstance()KeyPairGeneratorKeyPairGenerator.getInstance("RSA");

接下来,让我们来看看弹力城堡。弹力城堡库由两部分组成。一个是他们独特的加密库,您在上面的#2中尝试了其API。第二部分是大量的胶水代码,以允许将此库用作JCE的加密提供程序。这意味着作为程序员,您可以选择如何使用弹跳城堡加密库。您可以直接使用他们的API,如上面的#2所示。或者,您可以使用 JCE api,但通过类似 的方式显式指定弹跳城堡实现。KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");

如果您更喜欢直接使用独特的弹跳城堡API(他们称之为“轻量级API”),那么您就不需要所有用于使其作为JCE提供程序工作的胶水代码。对于这个弹跳城堡,它确实提供了轻量级API类的下载。

现在,我们终于来看看Android的实现。谷歌没有授权Oracle的Java源代码,所以他们没有任何Oracle的JCE提供商。他们必须提供自己的提供者。由于bouncycastle拥有所需的所有代码,并且是开源和自由许可的,因此Google / Android选择使用bouncycastle作为其默认JCE提供商的基础。但是,Android并没有努力为Android程序员提供独特的轻量级API。他们希望您仅通过 JCE 使用这些类。他们修改了弹跳式城堡代码,以针对Android进行调整。事实上,你可以直接在Android上找到并使用一些轻量级的API,这只是它在引擎盖下存在的一个副作用。并不是所有的东西都在那里。有些人将这种情况描述为“Android上的弹跳城堡已经瘫痪”。

为了在Android上提供一个功能齐全的弹跳城堡库版本,一些开发人员制作了一种叫做海绵木城堡库的东西。它只不过是修改了弹跳城堡库,以便它可以在Android上运行。主要修改是将包名称从 更改为 ,以防止命名空间冲突。org.bouncycastle.*org.spongycastle.*

那么你应该使用什么呢?这取决于你想做什么,你的可移植性需求是什么,你的风格偏好是什么,以及你的加密技能水平是什么。通常,当您使用这些库时,您正在以相当低的级别使用加密。您专注于如何执行此操作(使用RSA进行密钥传输,使用AES进行消息加密,使用HMAC-SHA256实现消息完整性等)而不是要做什么(我想通过类似电子邮件的机制向收件人发送加密消息)。显然,如果可以的话,你应该坚持使用直接解决你的问题的更高级别的库。这些库已经了解了PKCS#1是什么,以及如何将其用作更大,更完整的协议的一部分。


答案 2

今天早些时候,我正在帮助某人建造充气城堡。他的代码确实有效,所以检查一下

使用充气城堡生成的 RSA 密钥对。使代码可从 java 程序运行