我们正在尝试在 iOS 应用程序中添加“使用 Apple 登录”。当客户端工作正常时,我们的后端是用 Java 编写的,我们无法解码 Apple 的公钥。当您点击网址时https://appleid.apple.com/auth/keys https://appleid.apple.com/auth/keys它给你公钥。但是当我尝试做一个PublicKey
对象是 Java 它不识别n
and e
价值从那里。这些是 Base64 编码的吗?
当我尝试解码时n
and e
它给我的 Base64 值illegal character 2d
。我怀疑它是 base64 的原因是在 NodeJS 包中(https://www.npmjs.com/package/node-rsa https://www.npmjs.com/package/node-rsa)他们通过 base64 解码 n 和 e 值。但问题是指数值(e)是AQAB
它永远不可能是base64。我如何从中创建一个 PublicKey 对象?
我正在使用的代码是:
HttpResponse<String> responsePublicKeyApple = Unirest.get("https://appleid.apple.com/auth/keys").asString();
ApplePublicKeyResponse applePublicKeyResponse = new Gson().fromJson(responsePublicKeyApple.getBody(),ApplePublicKeyResponse.class);
System.out.println("N: "+applePublicKeyResponse.getKeys().get(0).getN());
System.out.println("E: "+applePublicKeyResponse.getKeys().get(0).getE());
byte[] decodedBytesE = Base64.getDecoder().decode(applePublicKeyResponse.getKeys().get(0).getE());
String decodedE = new String(decodedBytesE);
System.out.println("decode E: "+decodedE);
byte[] decodedBytesN = Base64.getDecoder().decode(applePublicKeyResponse.getKeys().get(0).getN());
String decodedN = new String(decodedBytesN);
System.out.println("decode N: "+decodedN);
BigInteger bigIntegerN = new BigInteger(decodedN,16);
BigInteger bigIntegerE = new BigInteger(decodedE,16);
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(bigIntegerN,bigIntegerE);
KeyFactory keyFactory = KeyFactory.getInstance(SignatureAlgorithm.RS256.getValue());
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
解码部分失败n
and e
价值。另一件事是苹果回应称他们使用了RS256
算法来签署令牌,但是当我尝试这样做时
KeyFactory keyFactory = KeyFactory.getInstance(SignatureAlgorithm.RS256.getValue());
it says RS256 keyfactory is not available
.
我该如何解决这两个问题?请帮忙。
其实那些N
and E
值使用编码Base64 网址 https://www.rfc-editor.org/rfc/rfc4648#page-7如中所解释的RFC7518 https://www.rfc-editor.org/rfc/rfc7518#page-30。此代码将向您展示如何执行您的请求。我使用 Jackson 来读取您提供的 JSON:
String json = Files.lines(Paths.get("src/main/resources/test.json")).collect(Collectors.joining());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// here is the parsing of PublicKey
ApplePublicKeyResponse applePublicKeyResponse = objectMapper.readValue(json, ApplePublicKeyResponse.class);
Key key = applePublicKeyResponse.getKeys().get(0);
byte[] nBytes = Base64.getUrlDecoder().decode(key.getN());
byte[] eBytes = Base64.getUrlDecoder().decode(key.getE());
BigInteger n = new BigInteger(1, nBytes);
BigInteger e = new BigInteger(1, eBytes);
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(n,e);
KeyFactory keyFactory = KeyFactory.getInstance(key.getKty()); //kty will be "RSA"
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
还如所指出的key.getKty()
将返回"RSA"
。所以你应该将此值传递给KeyFactory.getInstance
因为你想解析 RSA 密钥并且RS256
是使用 RSA 和 SHA-256 哈希的签名算法的名称。
我使用了构造函数BigInteger https://docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html#BigInteger-int-byte:A-它需要符号和原始字节。 Signum 设置为 1 以获得正值。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)