Android RSA密钥对生成-我应该使用标准Java/Bouncy Castle/Spongy Castle/JSch/Other吗?

Android RSA密钥对生成-我应该使用标准Java/Bouncy Castle/Spongy Castle/JSch/Other吗?,java,android,security,rsa,bouncycastle,Java,Android,Security,Rsa,Bouncycastle,我已经四处寻找了大约一个星期以上的时间来实现一个我想到的方法。我遇到(并阅读)了很多关于所有这些不同方法的文章,但我仍然感到困惑,所以我希望有人能传播他们对这些主题的知识,这样我就可以更轻松地创建我所追求的方法并在Android中实现它 我的“热门”方法: 必须生成RSA公钥和私钥 公众必须有PKCS#1填充 必须是RSA 2048 返回字节数组中的公钥 显然,你可以从四个方面着手: 标准Java 弹跳城堡 海绵城堡(Android友好型?) JSch 由于我对安全性和Java整体来说是个新手,

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

我的“热门”方法:

  • 必须生成RSA公钥和私钥
  • 公众必须有PKCS#1填充
  • 必须是RSA 2048
  • 返回字节数组中的公钥
  • 显然,你可以从四个方面着手:

  • 标准Java
  • 弹跳城堡
  • 海绵城堡(Android友好型?)
  • JSch
  • 由于我对安全性和Java整体来说是个新手,我想知道是否有人能最终对所有这些给出一个清晰的解释

    下面是我尝试在4种不同的编程方法中实现我追求的方法(如上所述)的方法。如果我不知道一些事情,那是因为我无法通过相应的文档来理解。请随时纠正我

    1.标准Java(不确定PKCS是否为1): 2.Bouncy Castle(尚未投入使用=/Ideas?): 3.SpongyCastle(没有启动它/与Bouncy Castle相同?): 4.JSch(非常不正常/正在进行的工作) 我希望这真的成为Android中RSA密钥生成有问题的任何人(像我和许多其他人一样)的一个资源


    我觉得Bouncy Castle关于API的信息很少,这使得初学者(像我一样)很难理解它。根据我的研究,人们在Java中使用Bouncy Castle而不是内置的安全提供者,因为Bouncy Castle更健壮。在Android中使用BouncyCastle是不可取的,因为它“附带了一个残缺版本的BouncyCastle”,可能会出错。海绵城堡只是弹性城堡的重新包装

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

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

    今天早些时候,我在帮别人处理bouncy castle。他的代码确实有效,所以请检查一下


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

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

    接下来,让我们看看bouncycastle。bouncycastle库由两部分组成。一个是他们独特的加密库,您已经在上面的#2中试用了它的API。第二部分是大量的粘合代码,允许该库用作JCE的密码提供者。这意味着作为程序员,您可以选择如何使用bouncycastle加密库。您可以直接使用它们的API,如上面的第2部分所示。或者,您可以使用JCE api,但通过类似于
    KeyPairGenerator kpg=KeyPairGenerator.getInstance(“RSA”、“BC”)的方式显式指定bouncycastle实现

    如果您喜欢直接使用唯一的bouncycastle API(他们称之为“轻量级API”),那么您就不需要使用所有的粘合代码来使其作为JCE提供者工作。为此,bouncycastle只提供了轻量级API类的下载

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

    为了在安卓系统上提供全功能版本的bouncycastle库,一些开发人员开发了一款名为。它只不过是修改了bouncycastle库,以便在Android上工作。主要修改是将包名从
    org更改。
    
    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;
    }
    
    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
    }
    
    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;
    }