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

在Java中加载原始的64字节长的ECDSA公钥

罗毅
2023-03-14
问题内容

我有原始(r,s)格式的ECDSA NISTP-256公钥。似乎没有简单的方法将其加载到实现java.security.interfaces.ECPublicKey的对象中。

加载64字节公共密钥以便可以用来检查签名的最干净的方法是什么?


问题答案:

EC功能需要Java 7,而Base 64编码器/解码器则需要Java8,没有其他库-仅是纯Java。请注意,打印出来时,这实际上会将公钥显示为已_命名的曲线_ ,而其他大多数解决方案都不会这样做。 如果您具有最新的运行时,则其他答案更为简洁。

如果我们使用进行此回答,将很难ECPublicKeySpec。因此,让我们作弊一下,X509EncodedKeySpec改用:

private static byte[] P256_HEAD = Base64.getDecoder().decode("MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE");

/**
 * Converts an uncompressed secp256r1 / P-256 public point to the EC public key it is representing.
 * @param w a 64 byte uncompressed EC point consisting of just a 256-bit X and Y
 * @return an <code>ECPublicKey</code> that the point represents 
 */
public static ECPublicKey generateP256PublicKeyFromFlatW(byte[] w) throws InvalidKeySpecException {
    byte[] encodedKey = new byte[P256_HEAD.length + w.length];
    System.arraycopy(P256_HEAD, 0, encodedKey, 0, P256_HEAD.length);
    System.arraycopy(w, 0, encodedKey, P256_HEAD.length, w.length);
    KeyFactory eckf;
    try {
        eckf = KeyFactory.getInstance("EC");
    } catch (NoSuchAlgorithmException e) {
        throw new IllegalStateException("EC key factory not present in runtime");
    }
    X509EncodedKeySpec ecpks = new X509EncodedKeySpec(encodedKey);
    return (ECPublicKey) eckf.generatePublic(ecpks);
}

用法:

ECPublicKey key = generateP256PublicKeyFromFlatW(w);
System.out.println(key);

其背后的想法是创建一个临时的X509编码密钥,该密钥愉快地以公共点w结尾。之前的字节包含命名曲线的OID的ASN.1
DER编码和结构开销,最后04一个字节指示未压缩的点。

删除未压缩点值的32字节X和Y值以创建标头。这仅适用于该点,因为该点是静态大小的-它在末端的位置仅由曲线的大小确定。

现在,该功能所需要做的generateP256PublicKeyFromFlatW就是将接收到的公共点添加w到标头,并通过为实现的解码器运行它X509EncodedKeySpec

上面的代码使用了原始的,未压缩的公共EC点-仅有32个字节的X和Y-没有带value的未压缩点指示符04。当然,也很容易支持65个字节的压缩点:

/**
 * Converts an uncompressed secp256r1 / P-256 public point to the EC public key it is representing.
 * @param w a 64 byte uncompressed EC point starting with <code>04</code>
 * @return an <code>ECPublicKey</code> that the point represents 
 */
public static ECPublicKey generateP256PublicKeyFromUncompressedW(byte[] w) throws InvalidKeySpecException {
    if (w[0] != 0x04) {
        throw new InvalidKeySpecException("w is not an uncompressed key");
    }
    return generateP256PublicKeyFromFlatW(Arrays.copyOfRange(w, 1, w.length));
}

最终,我P256_HEAD使用以下方法在base 64中生成了恒定的头值:

private static byte[] createHeadForNamedCurve(String name, int size)
        throws NoSuchAlgorithmException,
        InvalidAlgorithmParameterException, IOException {
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
    ECGenParameterSpec m = new ECGenParameterSpec(name);
    kpg.initialize(m);
    KeyPair kp = kpg.generateKeyPair();
    byte[] encoded = kp.getPublic().getEncoded();
    return Arrays.copyOf(encoded, encoded.length - 2 * (size / Byte.SIZE));
}

致电者:

String name = "NIST P-256";
int size = 256;
byte[] head = createHeadForNamedCurve(name, size);
System.out.println(Base64.getEncoder().encodeToString(head));


 类似资料:
  • 我有这个例子: 输出:[B@5fdef03a 有没有办法在具有相同输出的javascript中做到这一点?

  • 是否可以使用KeypairGenerator在java中生成ecdsa 32字节私钥?我的意思是keys.getpublic.getEncoded.length将返回32我尝试生成私钥,但大小是144字节

  • 我想使用OpenSSL rust crate来执行加密操作,特别是使用ECDSA算法。 我使用下面的代码来生成ECDSA密钥(椭圆曲线P-256 ),并使用它来签署数据和获取签名: 我不明白为什么< code>exact_bytes是70。以我的理解,应该是64。 对于签名过程中使用的曲线,ECDSA签名比签名者的私钥长2倍。例如,对于256位椭圆曲线(如secp256k1),ECDSA签名是51

  • 问题内容: 假定两个Java String对象: 那么对于表达式的每个值是否都是真的 评估为? 那么,是否保留String的任何值的原始字符串长度? 问题答案: 令人惊讶它 不是 ! 来自toLowerCase的 Java文档 使用给定语言环境的规则将此String中的所有字符转换为小写。大小写映射基于Character类指定的Unicode标准版本。 由于案例映射并不总是1:1字符映射,因此生成

  • 问题内容: 是否有一个Java库/示例可以读取Java中的JCE的openssh格式ecdsa公钥?我想将EC用于JWT。 我尝试读取的格式是按照authorized_keys或Github API(例如https://api.github.com/users/davidcarboni/keys)进行的: 我已经找到了这个答案,这对于RSA和DSS来说是很好的: 在Java安全中使用authori

  • 问题内容: 我得到了一些在程序中生成的Java字节码(即已编译的Java源代码)。现在,我想将此字节代码加载到当前运行的Java- VM中并运行特定功能。我不确定如何做到这一点,我对Java类加载器进行了一些研究,但没有找到直接的方法。 我找到了一个在硬盘上接收类文件的解决方案,但是我得到的字节码在字节数组中,我不想将其写入磁盘,而是直接使用它。 谢谢! 问题答案: 您需要编写一个自定义的类加载器