【问题标题】:Printing Elliptic Curve ASCII-Armor keys in Java [duplicate]用Java打印椭圆曲线ASCII-Armor键[重复]
【发布时间】:2020-03-31 10:58:45
【问题描述】:

我正在尝试使用 ES256_P-256 Elliptic Curve 键读取 JSON Web Keys (JWK),并将它们打印为 Java 中的装甲 ASCII。理想情况下,我希望在没有任何第三方库的情况下执行此操作,但我在 bouncycastle 和本机 Java 库方面都遇到了问题。不知道我做错了什么。这是 JWK:

{
  "kty": "EC",
  "d": "STNVdgaTJ7Lc7dpFShEPFVgYusUKzbYmb6492BknZFI",
  "use": "sig",
  "crv": "P-256",
  "kid": "1234",
  "x": "TrMA2sZ9CaNS3TWZRpjlLg1GB-AdAItozKSJe-83yHg",
  "y": "oeBo61jYweaEbIiMLF8r-ndDuQG73WmL2sGyqqUt8b4",
  "alg": "ES256"
}

和代码

import java.math.BigInteger;
import java.security.AlgorithmParameters;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.util.Base64;
import java.util.Base64.Decoder;
import java.util.Base64.Encoder;
import org.junit.Test;

public class KeyGenerator {

  @Test
  public void testGenerateECKey() {

    try {
      final Decoder decoder = Base64.getUrlDecoder();
      final Encoder encoder = Base64.getUrlEncoder();
      final byte[] secret = decoder
          .decode("STNVdgaTJ7Lc7dpFShEPFVgYusUKzbYmb6492BknZFI");
      final byte[] x_coord = decoder
          .decode("TrMA2sZ9CaNS3TWZRpjlLg1GB-AdAItozKSJe-83yHg");
      final byte[] y_coord = decoder
          .decode("oeBo61jYweaEbIiMLF8r-ndDuQG73WmL2sGyqqUt8b4");
      final BigInteger d = new BigInteger(1, secret);
      final BigInteger x = new BigInteger(1, x_coord);
      final BigInteger y = new BigInteger(1, y_coord);

      final AlgorithmParameters parameters = AlgorithmParameters
          .getInstance("EC");
      parameters.init(new ECGenParameterSpec("secp256r1"));
      final ECParameterSpec ecParameterSpec = parameters
          .getParameterSpec(ECParameterSpec.class);
      final KeyFactory keyFactory = KeyFactory.getInstance("EC");

      final ECPoint ecPoint = new ECPoint(x, y);
      final ECPublicKeySpec keySpec = new ECPublicKeySpec(ecPoint,
          ecParameterSpec);
      final ECPublicKey publicKey = (ECPublicKey) keyFactory
          .generatePublic(keySpec);

      final ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d,
          ecParameterSpec);
      final ECPrivateKey privateKey = (ECPrivateKey) keyFactory
          .generatePrivate(ecPrivateKeySpec);

      final KeyPair keyPair = new KeyPair(publicKey, privateKey);
      // final X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(
      // keyPair.getPublic().getEncoded());
      // final PKCS8EncodedKeySpec pKCS8EncodedKeySpec = new
      // PKCS8EncodedKeySpec(
      // keyPair.getPrivate().getEncoded());

      System.out.println("-----BEGIN PUBLIC KEY-----");
      System.out.println(keyPair.getPublic().getEncoded());
      System.out.println("-----END PUBLIC KEY-----");
      System.out.println("-----BEGIN PRIVATE KEY-----");
      System.out.println(keyPair.getPrivate().getEncoded());
      System.out.println("-----END PRIVATE KEY-----");

    } catch (final NoSuchAlgorithmException | InvalidKeySpecException
        | InvalidParameterSpecException ex) {
      ex.printStackTrace();
    }
  }

}

正在输出:

-----BEGIN PUBLIC KEY-----
[B@34340fab
-----END PUBLIC KEY-----
-----BEGIN PRIVATE KEY-----
[B@2aafb23c
-----END PRIVATE KEY-----

为什么 PEM 密钥这么小?我做错了什么?

【问题讨论】:

  • [B@34340fab 是字节数组toString 方法的结果。如果您想要 PEM,只需使用 Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded()) - 这将为您提供 DER 的 Base64。附在 BEGIN..END... 子句中,这是您的 PEM。

标签: java cryptography elliptic-curve java-security jwt-auth


【解决方案1】:

[B@34340fab 是字节数组 toString 方法的结果,您在尝试打印数组时隐式调用该方法。

PrivateKey::getEncodedPublicKey::getEncoded 将返回代表这些键的 DER 格式的 byte 数组。如果您想获得 PEM 格式,请使用 base64 对结果字节数组进行 jest 编码并添加 PEM 页眉/页脚:

String publicKeyBase64 = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
String privateKeyBase64 = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());

System.out.println("-----BEGIN PUBLIC KEY-----");
System.out.println(publicKeyBase64);
System.out.println("-----END PUBLIC KEY-----");
System.out.println("-----BEGIN PRIVATE KEY-----");
System.out.println(privateKeyBase64);
System.out.println("-----END PRIVATE KEY-----");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-25
    • 1970-01-01
    • 1970-01-01
    • 2016-10-04
    • 1970-01-01
    • 2013-11-14
    • 2018-05-20
    • 1970-01-01
    相关资源
    最近更新 更多