从JWK生成公钥 [英] Generating Public Key from JWK
问题描述
假设我有以下 JWK
作为某些 JWS
(RFC7515),出于显示目的,模数 n
被部分省略
Suppose I have the following JWK
as the deserialised body of some JWS
(RFC7515), where the modulus n
is partially omitted for display purposes
{
"kty": "RSA",
"e": "AQAB",
"kid": "KAgNpWbRyy9Mf2rikl498LThMrvkbZWHVSQOBC4VHU4",
"n": "llWmHF8XA2KNLdmxOP3kxD9OY76p0Sr37j..."
}
JWS
标头指定签名验证所需的 alg
和 kid
字段.
And the JWS
header specifies both the alg
and kid
fields required for signature verification.
如何从此 JWK
构建RSA公钥,以便可以验证签名?看过一些相关
How do I construct an RSA public key from this JWK
so that I can verify the signature? Having looked at some related questions, I have the following Java implementation that attempts to build an RSA public key from the n
and e
fields within the JWK
public void someMethod(){
String exjws ="eyJhbGciOiJSUzI1NiIsImtpZCI6IktBZ05wV2JSeXk5TWYycmlrbDQ5OExUaE1ydmtiWldIVlNRT0JDNFZIVTQiL"
+ "CJodG0iOiJwb3N0IiwiaHR1IjoiL3R4IiwidHMiOjE2MDM4MDA3ODN9.eyJjYXBhYmlsaXRpZXMiOltdLCJjbGllbnQiOnsia2V5Ijp7Imp3ayI6eyJrdHkiOiJSU0EiLCJ"
+ "hbGciOiJSUzI1NiIsImUiOiJBUUFCIiwia2lkIjoiS0FnTnBXYlJ5eTlNZjJyaW"
+ "tsNDk4TFRoTXJ2a2JaV0hWU1FPQkM0VkhVNCIsIm4iOiJsbFdtSEY4WEEyS05MZG14T1Aza3hEOU9ZNzZwMFNyMzdqZmh6OTRhOTN4bTJGTnFvU1BjUlpBUGQwbHFEUzhO"
+ "M1VpYTUzZEIyM1o1OU93WTRicE1fVmY4R0p2dnB0TFdueG8xUHlobVByIC0gZWNkU0NSUWRUY19aY01GNGhSVjQ4cXFsdnVEMG1xdGNEYklrU0JEdmNjSm1aSHdmVHBESG"
+ "luVDh0dHZjVlA4VmtBTUFxNGtWYXp4T3BNb0lSc295RXBfZUNlNXBTd3FIbzBkYUNXTktSI"
+ "C0gRXBLbTZOaU90ZWRGNE91bXQ4TkxLVFZqZllnRkhlQkRk"
+ "Q2JyckVUZDR2Qk13RHRBbmpQcjNDVkN3d3gyYkFRVDZTbHhGSjNmajJoaHlJcHE3cGM4clppYjVqTnlYS3dmQnVrVFZZWm96a3NodCAtIExvaHlBU2FLcFlUcDhMdE5aIC0gdyAifSw"
+ "icHJvb2YiOiJqd3MifSwibmFtZSI6Ik15IEZpcnN0IENsaWVu"
+ "dCIsInVyaSI6Imh0dHA6XC9cL2xvY2FsaG9zdFwvY2xpZW50XC9jbGllbnRJRCJ9LCJpbnRlcmFjdCI6eyJzdGFydCI6WyJyZWRpcmVjdCJ"
+ "dLCJmaW5pc2giOnsibWV0aG9kIjoicmVkaXJlY3QiLCJub25jZSI6ImQ5MDIxMzg4NGI4NDA5MjA1MzhiNWM1MSIsInVyaSI6Imh0dHA6XC9cL2xvY2FsaG9zdFwvY2xpZW50"
+ "XC9yZXF1ZXN0LWRvbmUifX0sImFjY2Vzc190b2tlbiI6eyJhY2Nlc3MiOlt7ImFjdGlvbnMiOlsicmVhZCIsInByaW50Il0sImxvY2F0aW9ucyI6WyJodHRwOlwvXC9sb2Nhb"
+ "Ghvc3RcL3Bob3RvcyJdLCJkYXRhdHlwZXMiOlsibWV0YWRhdGEiLCJpbWFnZXMiXSwidHlwZSI6InBob3RvLWFwaSJ9XX0sInN1YmplY3QiOnsic3ViX2lkcyI6WyJpc3Nfc3"
+ "ViIiwiZW1haWwiXX19.LUyZ8_fERmxbYARq8kBYMwzcd8GnCAKAlo2ZSYLRRNAYWPrp2XGLJOvg97WK1idf_LB08OJmLVsCXxCvn9mgaAkYNL_ZjHcusBvY1mNo0E1sdTEr31"
+ "CVKfC-6WrZCscb8YqE4Ayhh0Te8kzSng3OkLdy7xN4xeKuHzpF7yGsM52JZ0cBcTo6WrYEfGdr08AWQJ59ht72n3jTsmYNy9A6I4Wrvfgj3TNxmwYojpBAi"
+ "cfjnzA1UVcNm9F_xiSz1_y2tdH7j5rVqBMQife-k9Ewk95vr3lurthenliYSNiUinVfoW1ybnaIBcTtP1_YCxg_h1y-B5uZEvYNGCuoCqa6IQ";
String[] parts = exjws.split("\\.");
String payload = new Base64URL(parts[1]).decodeToString();
JsonObject jwk = JsonParser.parseString(payload).getAsJsonObject().get("client")
.getAsJsonObject().get("key").getAsJsonObject().get("jwk").getAsJsonObject();
BigInteger modulus = new BigInteger(1, new Base64URL(jwk.get("n").getAsString()).decode());
BigInteger exponent = new BigInteger(1, new Base64URL(jwk.get("e").getAsString()).decode());
byte[] signingInfo = String.join(".",parts[0],parts[1]).getBytes(StandardCharsets.UTF_8);
byte[] b64DecodedSig = new Base64(parts[2]).decode();
PublicKey pub = KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, exponent));
Signature verifier = Signature.getInstance("SHA256withRSA");
verifier.initVerify(pub);
verifier.update(signingInfo);
boolean okay = verifier.verify(b64DecodedSig);
System.out.println(okay);
}
verify()
的结果当前返回 false
.
我尝试生成RSA密钥对,并使用生成的密钥和有效的进行签名和验证.我怀疑我的问题是上面代码中构造的RSA密钥以某种方式是错误的.任何帮助表示赞赏.
I have tried generating RSA key pairs, signing and verifying using the generate keys and that worked. I suspect that my issue is that the constructed RSA key in the code above is wrong somehow. Any help appreciated.
编辑
JSON库是 Gson
JWK
库是 nismus-jose-jwt
,它提供 Base64
和 Base64URl
推荐答案
摘自与@Topaco的讨论:
From the discussion with @Topaco in the comments:
问题中的代码确实通过模数 n
和指数 e
成功构建了RSA公钥.
The code in the question does successfully construct the RSA public key from the modulus n
and the exponent e
.
但是,由于请求中 JWK
中指定的公钥与 Signature.verify()
调用返回 false
,因此返回 false
.用于签署请求的密钥.
However, the Signature.verify()
invocation returns false
because the public key specified within the JWK
in the request does not match the key used to sign the request.
这篇关于从JWK生成公钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!