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

EGH*_*HDK 34 java security android rsa bouncycastle

我一直在寻找一周左右的时间来实现我想到的方法.我已经看过很多关于所有这些不同方法的文章,但我仍然感到困惑,所以我希望有人可以传播他们对这些主题的知识,这样我就可以更轻松地创建我追捧的方法和在Android中实现它.

我的"追捧"方法:

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

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

  1. 标准Java
  2. 充气城堡
  3. 海绵城堡(Android友好?)
  4. JSch

由于我对安全性和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;
}
Run Code Online (Sandbox Code Playgroud)

2. Bouncy Castle(尚未功能= /创意?):

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
}
Run Code Online (Sandbox Code Playgroud)

3. SpongyCastle(Havnot开始它/与Bouncy Castle相同?):

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;
}
Run Code Online (Sandbox Code Playgroud)

对于那些在Android中遇到RSA密钥生成问题的人来说,我真的希望这能成为更多的资源(就像我和许多其他人一样).


我觉得,充气城堡有很少的信息,关于它的API,这使得它非常困难的初学者(像我)去了解它.根据我的研究,人们使用Java中的Bouncy Castle而不是内置的安全提供程序,因为Bouncy Castle更加强大.在Android中使用Bouncy Castle是不可取的,因为它"携带一个残缺的版本的Bouncy Castle",可能容易出错.Spongy Castle简直就是Bouncy Castle 的重新包装.

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

更新

我希望有人可以稍后回答这个问题.至于我做了什么来解决我的问题是只使用NDK.

Jam*_*olk 46

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

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

接下来,让我们看一下bouncycastle.bouncycastle图书馆由两部分组成.一个是他们独特的加密库,您已经在上面的#2中进行了实验.第二部分是很多粘合代码,允许这个库用作JCE的crypt提供者.这意味着您作为程序员可以选择如何使用bouncycastle加密库.您可以像上面的#2一样直接使用他们的API.或者,您可以使用JCE api,但通过类似的方式明确指定bouncycastle实现KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");.

如果您更喜欢直接使用独特的bouncycastle API(他们称之为"轻量级API"),那么您就不需要使用所有粘合代码来使其作为JCE提供程序工作.对于这个bouncycastle确实提供了轻量级API类的下载.

现在,最后,我们来看看Android的实现.Google未授权Oracle的Java源代码,因此他们没有任何Oracle的JCE提供商.他们必须提供自己的提供者.由于bouncycastle拥有所需的所有代码,并且是开源和自由许可的,因此Google/Android选择使用bouncycastle作为其默认JCE提供商的基础.但是,Android并没有努力为Android程序员提供独特的轻量级API.他们希望您仅通过JCE使用这些课程.他们修改了bouncycastle代码以针对Android调整它.事实上,你可以在Android上找到并且可能直接使用一些轻量级API,这只不过是它在幕后的事实的副作用.并非一切都在那里.有些人将这种情况描述为"Android上的bouncycastle已经瘫痪".

为了在Android上实际提供bouncycastle库的全功能版本,一些开发人员制作了一个名为Spongycastle库的东西.它只不过是修改过的bouncycastle库,因此它可以在Android上运行.主要修改是将包名称更改org.bouncycastle.*org.spongycastle.*以防止命名空间冲突.

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