現在、Sign in with Apple の実装を行っています。
サーバサイドは、Javaを使用しています。
その中で、Appleが返却してきたJWTを、
https://appleid.apple.com/auth/keys
の、公開鍵で検証してやる必要があるのですが、
https://appleid.apple.com/auth/keys
のjsonから、どうやって、
java.security.interfaces.RSAPublicKey
のインスタンスを生成して良いか分かりません。
どなたか教えて頂けないでしょうか?
jwtのライブラリは、
https://github.com/auth0/java-jwt
を利用しようとしています。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
自己解決
解決しました。
同じ問題で躓いている人のために、
動作検証済みのコードを載せておきます。
ライブラリは
https://github.com/auth0/java-jwt
と、その依存ライブラリおよび
https://github.com/stleary/JSON-java
を入れました。
java
1package jp.sample; 2 3import java.io.BufferedReader; 4import java.io.IOException; 5import java.io.InputStream; 6import java.io.InputStreamReader; 7import java.math.BigInteger; 8import java.net.HttpURLConnection; 9import java.net.URL; 10import java.security.KeyFactory; 11import java.security.NoSuchAlgorithmException; 12import java.security.interfaces.RSAPublicKey; 13import java.security.spec.InvalidKeySpecException; 14import java.security.spec.RSAPublicKeySpec; 15import java.util.Base64; 16 17import org.json.JSONArray; 18import org.json.JSONObject; 19 20import com.auth0.jwt.JWT; 21import com.auth0.jwt.algorithms.Algorithm; 22import com.auth0.jwt.exceptions.JWTVerificationException; 23import com.auth0.jwt.interfaces.JWTVerifier; 24 25public class Sample01JwtVerify { 26 27 /** 28 * 29 * SIWAのJWT検証サンプル 30 * 31 */ 32 public void test() { 33 34 // テスト対象のトークン 35 // ここに、iOSの ASAuthorizationAppleIDCredentialのインスタンスの 36 // 「identityToken」をutf8として解釈した文字列を入れる。 37 String token ="ヘッダー.ペイロード.署名"; 38 39 //---------------------------------------------------------- 40 // ■STEP1 41 // Appleサーバより公開鍵を取得 42 //---------------------------------------------------------- 43 // Appleの公開鍵のURL 44 String strUrl = "https://appleid.apple.com/auth/keys"; 45 46 HttpURLConnection urlConn = null; 47 InputStream in = null; 48 BufferedReader reader = null; 49 String jsonString = null; 50 51 try { 52 53 URL url = new URL(strUrl); 54 urlConn = (HttpURLConnection) url.openConnection(); 55 urlConn.setRequestMethod("GET"); 56 urlConn.connect(); 57 int status = urlConn.getResponseCode(); 58 System.out.println("HTTPステータス:" + status); 59 60 if (status == HttpURLConnection.HTTP_OK) { 61 62 in = urlConn.getInputStream(); 63 reader = new BufferedReader(new InputStreamReader(in)); 64 StringBuilder output = new StringBuilder(); 65 String line; 66 67 while ((line = reader.readLine()) != null) { 68 output.append(line); 69 } 70 71 jsonString = output.toString(); 72 System.out.println("jsonString=" + jsonString); 73 } 74 } catch (IOException e) { 75 e.printStackTrace(); 76 } finally { 77 try { 78 if (reader != null) { 79 reader.close(); 80 } 81 if (urlConn != null) { 82 urlConn.disconnect(); 83 } 84 } catch (IOException e) { 85 e.printStackTrace(); 86 } 87 } 88 // JSON解析 89 JSONObject jsonRoot = new JSONObject(jsonString); 90 91 // keys 92 JSONArray array = jsonRoot.getJSONArray("keys"); 93 94 // key 95 JSONObject key = array.getJSONObject(0); 96 97 // n 98 String n = key.getString("n"); 99 System.out.println("n=" + n); 100 101 // e 102 String e = key.getString("e"); 103 System.out.println("e=" + e); 104 105 //---------------------------------------------------------- 106 // ■STEP2 107 // n(modulus)と、e(publicExponent)を、Base64UrlSafeでデコード 108 //---------------------------------------------------------- 109 Base64.Decoder decorder = Base64.getUrlDecoder(); 110 byte[] modulusBytes = decorder.decode(n); 111 byte[] publicExponentBytes = decorder.decode(e); 112 113 //---------------------------------------------------------- 114 // ■STEP3 115 // 4ビットずつ16進表記に変換 116 //---------------------------------------------------------- 117 String modulusHex = bytesToHex2(modulusBytes); 118 String publicExponentHex = bytesToHex2(publicExponentBytes); 119 System.out.println("modulusHex=" + modulusHex); 120 System.out.println("publicExponentHex=" + publicExponentHex); 121 122 //---------------------------------------------------------- 123 // ■STEP4 124 // BigInteger化する。 125 //---------------------------------------------------------- 126 BigInteger modulesBigInt = new BigInteger(modulusHex, 16); 127 BigInteger exponentBigInt = new BigInteger(publicExponentHex, 16); 128 129 //---------------------------------------------------------- 130 // ■STEP5 131 // RSAPublicKeySpec化する。 132 //---------------------------------------------------------- 133 RSAPublicKeySpec rsaPubKS = new RSAPublicKeySpec(modulesBigInt , exponentBigInt); 134 135 //---------------------------------------------------------- 136 // ■STEP6 137 // RSAPublicKey化する。 138 //---------------------------------------------------------- 139 KeyFactory kf = null; 140 RSAPublicKey publicKey = null; 141 try { 142 kf = KeyFactory.getInstance("RSA"); 143 publicKey = (RSAPublicKey) kf.generatePublic(rsaPubKS); 144 145 } catch (NoSuchAlgorithmException e1) { 146 e1.printStackTrace(); 147 } catch (InvalidKeySpecException e2) { 148 e2.printStackTrace(); 149 } 150 //---------------------------------------------------------- 151 // ■STEP7 152 // 認証する。 153 //---------------------------------------------------------- 154 try { 155 Algorithm algorithm = Algorithm.RSA256(publicKey, null); 156 JWTVerifier verifier = JWT.require(algorithm) 157 .withIssuer("https://appleid.apple.com") 158 .build(); 159 160 verifier.verify(token); 161 162 } catch (JWTVerificationException e3){ 163 164 System.out.println("認証NG"); 165 166 } catch (Exception e4) { 167 e4.printStackTrace(); 168 } 169 System.out.println("認証OK"); 170 } 171 /** 172 * 173 * byte配列を16進数の文字列に変換 174 * 175 * @param hashInBytes 176 * @return 177 */ 178 private String bytesToHex2(byte[] hashInBytes) { 179 180 StringBuilder sb = new StringBuilder(); 181 for (int i = 0; i < hashInBytes.length; i++) { 182 String hex = Integer.toHexString(0xff & hashInBytes[i]); 183 if (hex.length() == 1) sb.append('0'); 184 sb.append(hex); 185 } 186 return sb.toString(); 187 } 188 189} 190
投稿2019/10/29 10:31
総合スコア9
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。