是否有一个Java库/示例可以读取PublicKeyJava中的JCE的openssh格式ecdsa公钥?我想将EC用于JWT。
PublicKey
我尝试读取的格式是按照authorized_keys或Github API(例如https://api.github.com/users/davidcarboni/keys)进行的: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK8hPtB72/sfYgNw1WTska2DNOJFx+QhUxuV6OLINSD2ty+6gxcM8yZrvMqWdMePGRb2cGh8L/0bGOk+64IQ/pM=
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK8hPtB72/sfYgNw1WTska2DNOJFx+QhUxuV6OLINSD2ty+6gxcM8yZrvMqWdMePGRb2cGh8L/0bGOk+64IQ/pM=
我已经找到了这个答案,这对于RSA和DSS来说是很好的: 在Java安全中使用authorized_keys中的公钥,并讨论ECDSA的openssh格式:https : //security.stackexchange.com/questions/129910/ecdsa-为什么ssh- keygen和java生成的公共密钥具有不同的大小
但是,我迷失了尝试将RSS / DSA代码改编为ECDSA的方法- 我不确定如何设置ECPublicKeySpec。它需要ECPoint,EllipticCurve,ECParameterSpec,ECField。openssh格式仅包含两个整数,这对于有意义ECPoint,但我不知道如何设置其余整数。
ECPublicKeySpec
ECPoint
EllipticCurve
ECParameterSpec
ECField
我一直在闲逛一堆库,包括jsch,sshj,ssh- tools和不错的老Bouncycastle。我最近的是:
com.jcraft.jsch.KeyPair load = com.jcraft.jsch.KeyPair.load(jsch, null, bytes[openSshKey]);
可以很好地加载密钥,但不能让我进入JCE- PublicKey只是一种byte[] getPublicKeyBlob()方法。
byte[] getPublicKeyBlob()
我是否缺少明显的东西?
为了完整起见,这是我使用的代码。它是几乎纯的JCE,在帮助器方法中散布了Bouncycastle(这会更新Java安全中的“使用authorized_keys中的公共密钥”中的示例代码):
... } else if (type.startsWith("ecdsa-sha2-") && (type.endsWith("nistp256") || type.endsWith("nistp384") || type.endsWith("nistp521"))) { // Based on RFC 5656, section 3.1 (https://tools.ietf.org/html/rfc5656#section-3.1) String identifier = decodeType(); BigInteger q = decodeBigInt(); ECPoint ecPoint = getECPoint(q, identifier); ECParameterSpec ecParameterSpec = getECParameterSpec(identifier); ECPublicKeySpec spec = new ECPublicKeySpec(ecPoint, ecParameterSpec); return KeyFactory.getInstance("EC").generatePublic(spec); } ... /** * Provides a means to get from a parsed Q value to the X and Y point values. * that can be used to create and ECPoint compatible with ECPublicKeySpec. * * @param q According to RFC 5656: * "Q is the public key encoded from an elliptic curve point into an octet string" * @param identifier According to RFC 5656: * "The string [identifier] is the identifier of the elliptic curve domain parameters." * @return An ECPoint suitable for creating a JCE ECPublicKeySpec. */ ECPoint getECPoint(BigInteger q, String identifier) { String name = identifier.replace("nist", "sec") + "r1"; ECNamedCurveParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec(name); org.bouncycastle.math.ec.ECPoint point = ecSpec.getCurve().decodePoint(q.toByteArray()); BigInteger x = point.getAffineXCoord().toBigInteger(); BigInteger y = point.getAffineYCoord().toBigInteger(); System.out.println("BC x = " + x); System.out.println("BC y = " + y); return new ECPoint(x, y); } /** * Gets the curve parameters for the given key type identifier. * * @param identifier According to RFC 5656: * "The string [identifier] is the identifier of the elliptic curve domain parameters." * @return An ECParameterSpec suitable for creating a JCE ECPublicKeySpec. */ ECParameterSpec getECParameterSpec(String identifier) { try { // http://www.bouncycastle.org/wiki/pages/viewpage.action?pageId=362269#SupportedCurves(ECDSAandECGOST)-NIST(aliasesforSECcurves) String name = identifier.replace("nist", "sec") + "r1"; AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC"); parameters.init(new ECGenParameterSpec(name)); return parameters.getParameterSpec(ECParameterSpec.class); } catch (InvalidParameterSpecException | NoSuchAlgorithmException e) { throw new IllegalArgumentException("Unable to get parameter spec for identifier " + identifier, e); } }