当前位置: 首页 > 面试题库 >

Java ECC编码的密钥太大

柯星华
2023-03-14
问题内容

我是EC加密的新手,对此有些挣扎。我正在使用Java 8和BouncyCatle提供程序。现在的问题是:当我使用以下代码生成EC-KeyPair时:

    ECGenParameterSpec spec = new ECGenParameterSpec("secp521r1");
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDH", BouncyCastleProvider.PROVIDER_NAME);
    kpg.initialize(spec, new SecureRandom());
    return kpg.generateKeyPair();

并尝试获取公用密钥的字节数组以将其发送给其他人,编码密钥的长度为158个字节,格式为X.509。但是我期望X9.62格式和65到66字节之间的密钥大小。为什么公钥这么大,我如何用期望的密钥大小对其进行编码?(我期望密钥的大小,因为我期望密钥的长度为521位)


问题答案:

ECC公钥在语义上是曲线上的一个点;如果隐含了您命名的曲线,则X9.62格式的点如果经过压缩,则为67个八位位组(Java字节),如果为未压缩,则为133个八位位组,从没有其他长度。

如果您的意思java.security.PublicKey.getEncoded()始终是Java所谓的“
X.509”编码,则实际上是SubjectPublicKeyInfoX.509中定义的ASN.1结构(SPKI),并且更方便地在rfc5280 sec
4.1
中使用DER编码。对于这种格式,曲线上的ECC公钥准确地是90或158个八位位组,用于未压缩或已压缩,并且Java提供程序(至少当前)生成未压缩的形式(尽管它们可以
解析 压缩的形式)。

听起来您可能想要X9.62压缩格式,正如我所说的,它是67字节(不是65或66)。如果是这样,您将无法在标准Java
API中控制点压缩,但是考虑到BC提供程序创建了关键对象,BouncyCastle实现类确实支持它。首先将keypair.getPublicKey()
强制转换
(corr)org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey(在1.47
was之前org.bouncycastle.jce.provider.JCEECPublicKey),然后getQ()返回一个org.bouncycastle.math.ec.ECPoint包含(重载)的getEncoded(boolean compressed),它会产生您显然想要的内容。

对于您的另一个但还不是正式的问题,PublicKey要从编码点(压缩与否)重新创建对象,您可以根据计算方式有两个或三个选项:

  • 为此曲线和点构造一个ASN.1 / DER编码的SubjectPublicKeyInfo结构(Java称为“ X.509”格式),将其放入X509EncodedKeySpec并通过适当的运行KeyFactory。可以使用标准的SunEC提供程序(假定为j7 +,而不是RedHat限制版本)或BC提供程序。通常很难手动构造像SPKI这样的ASN.1编码,但在这种情况下还不错。或如果您拥有BC,则可以使用其ASN.1功能

  • 直接致电BC程序做什么欧共体的KeyFactory 针对上述输入做

创建点然后使用这三种方式的示例代码:

// as needed in addition to standard java.security and javax.html" target="_blank">xml 
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;

    KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "BC");
    kpg.initialize(new ECGenParameterSpec("secp521r1"));
    org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey ku = 
            (org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey)kpg.generateKeyPair().getPublic();
    byte[] encodedpoint = ku.getQ().getEncoded(true/*compressed*/);

    { // construct SPKI by hand, this curve only
        byte[] hdr = DatatypeConverter.parseHexBinary("3058301006072a8648ce3d020106052b81040023034400");
        // could also write out byte[] hdr = {0x30,0x58,0x30,0x10... but items with 0x80 set need casts
        if( 0x44 /*hdr[0x15]*/ -1 != encodedpoint.length ) throw new Exception ("BAD COMPRESSED POINT FOR secp521r1!");
        byte[] spki = Arrays.copyOf(hdr,90); System.arraycopy(encodedpoint,0, spki,0x17, 0x43);
        PublicKey k2 = KeyFactory.getInstance("EC" /*,provider?*/).generatePublic(new X509EncodedKeySpec(spki));
        Signature.getInstance("ECDSA").initVerify(k2); // sanity check
    }
    { // construct SPKI with BC
        AlgorithmIdentifier algid = new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey,SECObjectIdentifiers.secp521r1);
        ASN1EncodableVector vec = new ASN1EncodableVector();
        vec.add(algid); vec.add(new DERBitString(encodedpoint));
        byte[] spki = new DERSequence(vec).getEncoded();
        PublicKey k2 = KeyFactory.getInstance("EC" /*,provider*/).generatePublic(new X509EncodedKeySpec(spki));
        Signature.getInstance("ECDSA").initVerify(k2); // sanity check
    }
    { // call BC directly
        ProviderConfiguration configuration = BouncyCastleProvider.CONFIGURATION;
        X962Parameters params = X962Parameters.getInstance(org.bouncycastle.asn1.sec.SECObjectIdentifiers.secp521r1);
        ECCurve curve = EC5Util.getCurve(configuration, params);
        /*ECParameterSpec ecSpec = EC5Util.convertToSpec(params, curve);*/
        ECPoint point = curve.decodePoint(encodedpoint).normalize();
        ECPublicKeyParameters kparams = new ECPublicKeyParameters(point, ECUtil.getDomainParameters(configuration, params));
        PublicKey k2 = new BCECPublicKey ("EC"/* or "ECDH" etc*/, kparams, configuration);
        Signature.getInstance("ECDSA").initVerify(k2); // sanity check
    }

相关信息在Java中加载未经压缩的P256
原始64字节长的ECDSA公共密钥。



 类似资料:
  • 我是EC加密的新手,对它有一些困难。我正在使用Java8和BouncyCatle提供程序。我现在的问题是:当我使用以下代码生成EC密钥对时: 并尝试获取公钥的字节数组以将其发送给另一个人,编码密钥长158字节,格式为X.509。但我期望X9.62格式和65到66字节之间的密钥大小。为什么公钥这么大?我如何用预期的密钥大小对其进行编码?(我期望密钥大小,因为我期望密钥长度为521位。)

  • 我用过这个命令 生成密钥库。它工作正常,但从我读到的内容来看,这个命令还应该提示您输入密钥密码(而不是存储密码)?我从来没有收到过这样的提示。我能跑 查看密钥库的内容。钥匙似乎就在那里。。。正确的别名在那里。在哪里获取/设置特定别名的密码? 我有一个key.properties在Android目录 在build.gradle我有: 当我试图生成一个发布版本时,我得到了 我想它可能与keyPassw

  • 问题内容: 我无法在上创建索引。 MySQL: 问题答案:

  • 问题内容: 当我执行以下命令时: 我收到此错误消息: 有关column1和column2的信息: 我认为只需要21个字节,而只需要501个字节。因此,总字节数是522,少于767。那么为什么收到错误消息? 问题答案: 在MySQL版本5.6(及更早版本)中,InnoDB表的前缀限制为767个字节。MyISAM表的长度为1,000字节。在MySQL 5.7及更高版本中,此限制已增加到3072字节。

  • 问题内容: 我正在通过SSL连接到数据库Google Cloud SQL。我使用codeigniter 3.0进行了此操作,尽管mysqli驱动程序进行了一些修改以允许此功能。 几个月来一直运作良好。但是,它 刚刚 开始返回此警告: 我认为这是主要问题,但我不知道那是什么意思。我已经搜索了Diffie- Hellman密钥交换以及“密钥太小”消息,但是运气不高。 这是否表明服务器上的密钥已被篡改?

  • 问题内容: 我知道有关此标题的问题已经回答过,但是请继续阅读。发布前,我已彻底阅读了关于此错误的所有其他问题/答案。 我收到以下查询的上述错误: 有谁知道为什么以及如何解决它?问题是-相同的查询在我的本地计算机上运行完美,在我以前的主机上也运行良好。顺便说一句,它来自一个成熟的项目- phpdevshell-所以我猜这些家伙知道他们在做什么,尽管你永远都不知道。 任何线索表示赞赏。 我正在使用ph