Android无法创建EC Keypair



如标题中所述,我无法制作以下代码产生ECC Keypair。

例外是: java.security.InvalidParameterException: unknown key size 571

在台式机上,571是最大密钥大小,我也打算在Android应用程序上使用最大密钥大小。我该怎么做才能使它成为可能?

接下来,可以通过Android和桌面上的其他库制作更大的钥匙?

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Thread thread = new Thread(){
        public void run(){
            try{
                setPriority(Thread.MAX_PRIORITY);
                SecureRandom secureRandom = new SecureRandom();
                KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
                generator.initialize(571, secureRandom);
                KeyPair keyPair = generator.generateKeyPair();
                PublicKey publicKey = keyPair.getPublic();
                PrivateKey privateKey = keyPair.getPrivate();
                System.out.println("EC public: " + publicKey.getAlgorithm() + "t" + publicKey.getFormat());
                System.out.println("EC private: " + privateKey.getAlgorithm() + "t" + publicKey.getFormat());
            }
            catch(Exception e){
                System.err.println("EC Exceptionn" + e.toString());
                e.printStackTrace();
            }
        }
    };
    thread.start();
}

无需使用571位曲线。具有512位密钥或更高的曲线可提供256位的安全性。这足够了 - 直到量子计算达到年龄,在这种情况下都不足够。使用大型量子计算机使用离散对数问题(ECDL(的椭圆曲线加密的安全性,带有足够大的量子计算机将接近零。

当前,大多数标准都使用Prime曲线(F(P(上的曲线(或Edwards曲线,例如Curve25519(ED25519和X25519(。指定571时所使用的可能是f(2^m(上称为Sect571R1标准化为K-571的曲线。那是二进制/koblitz曲线;二进制曲线目前不经常使用,并且每个提供商可能都不可用。直到Java 18没有支持二进制曲线。

Java 18确实支持Prime和Edwards曲线,例如ED25519,您可以在查看安全性时看到 - >提供者 - >Sunec提供商指南,部分"支持椭圆曲线名称"。目前,它支持SECP256R1,SECP384R1和SECP521R1用于签名生成和关键协议,ED25519和ED448用于签名生成,以及X25519和X448,以及X448以符合关键协议。自Java 11(Java的最后一个LTS版本(以来,这些。

选择以这种方式的特定曲线并不十分清楚,并且可能会产生后果。如果使用其他曲线是因为添加了另一个提供商实现相同大小的曲线怎么办?

相反,如果要坚持在素数上命名的强曲线,请使用以下代码:

KeyPairGenerator generator = KeyPairGenerator.getInstance("EC");
generator.initialize(new ECGenParameterSpec("secp521r1"));
KeyPair keyPair = generator.generateKeyPair();
ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic();
ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate();

很适合糖,使用曲线的实际名称,而不仅仅是位大小,即 ECGenParameterSpec。您真的不想自己生成曲线域参数,也不想使用适合位大小的任何曲线。通常,使用密码学,除非标准明确定义它们。

,我不会使用任何默认值。

您还可以尝试添加一个提供商(Java的Bouncycastle和后期版本的Android,Spongycastle,用于Android的早期版本(,以获得更多曲线的支持。确保在这种情况下指定要用于发电机的提供商。我会认真建议使用上述的

提防SUNEC提供的KeyPairGeneratorSignature的实现可能会坚持他们可以处理软件定义的EC键,而它们与这些曲线名称不兼容。这意味着您需要明确使用Bouncycastle或Spongycastle提供商,而不是简单地将提供商添加到已知列表中:

Provider bc = new BouncyCastleProvider();
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", bc);
kpg.initialize(new ECGenParameterSpec("K-571")); // "sect571r1" also works
KeyPair kp = kpg.generateKeyPair();
Signature sig = Signature.getInstance("SHA512WithECDSA", bc);
sig.initSign(kp.getPrivate());
sig.sign();

您仅限于一组NIST批准的EC曲线,您没有carte blanche。

此外,如果您使用的是硬件支持的Android密钥库(这将是越来越多的情况(,则仅对特定的密钥参数组合有硬件支持 - 例如,目前(2020/11(仅1024 - 和2048位RSA键在硬件中支持,但不支持4096位。

最新更新