java生成openssh公钥,在Java Security中使用openssh公钥(ecdsa-sha2-nistp256)

Is there a Java library/example to read an openssh format ecdsa public key to a JCE PublicKey in Java? I want to use EC for JWT .

The format I'm trying to read is as per authorized_keys, or Github API (e.g. https://api.github.com/users/davidcarboni/keys): ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK8hPtB72/sfYgNw1WTska2DNOJFx+QhUxuV6OLINSD2ty+6gxcM8yZrvMqWdMePGRb2cGh8L/0bGOk+64IQ/pM=

However I'm getting lost trying to adapt the RSS/DSA code for ECDSA - I'm not sure how to set up an ECPublicKeySpec. It needs ECPoint, EllipticCurve, ECParameterSpec, ECField. The openssh format only contains two integers, which makes sense for ECPoint, but I don't know how to set up the rest.

I've been poking around a bunch of libraries, including jsch, sshj, ssh-tools and good old Bouncycastle. The closest I have is:

com.jcraft.jsch.KeyPair load = com.jcraft.jsch.KeyPair.load(jsch, null, bytes[openSshKey]);

Which loads the key fine, but doesn't get me to a JCE PublicKey - just a byte[] getPublicKeyBlob() method.

Am I missing something obvious?

解决方案

For completeness, here's the code I've gone with. It's nearly-pure JCE, with a sprinkling of Bouncycastle inside helper methods (this updates the example code in Using public key from authorized_keys with Java security):

...

} 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);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值