質問編集履歴

10

修正

2022/05/18 15:44

投稿

pp02
pp02

スコア4

test CHANGED
File without changes
test CHANGED
@@ -18,7 +18,7 @@
18
18
  ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-05-18/0007e21f-8c06-4158-baeb-123b08ee1c18.png)
19
19
 
20
20
  ### 発生している問題・エラーメッセージ
21
- java-jwt で、RSA256アルゴリズムで暗号化するためはRSAPrivateKey型の秘密鍵を指定する必要るのですが、秘密鍵を**String型の状態からどのようにしてRSAPrivateKey型に変換するかが分からない**状態です。また、参考例だけではどのようにRS256による電子署名を行うのかが具体的に理解するとができせんでした
21
+ プログラム自体正常動いてJWT生成されるのですが、Postmanを用いLINEWORKS APIしよするとエラー発生してしいます
22
22
  そのため、以下の2点を質問させてください。
23
23
 
24
24
  ①string型の秘密鍵を RSAPrivateKey型に変える方法は「該当のソースコード」項目に記載してあるような方法で合っているか?

9

修正

2022/05/18 15:13

投稿

pp02
pp02

スコア4

test CHANGED
File without changes
test CHANGED
@@ -22,6 +22,7 @@
22
22
  そのため、以下の2点を質問させてください。
23
23
 
24
24
  ①string型の秘密鍵を RSAPrivateKey型に変える方法は「該当のソースコード」項目に記載してあるような方法で合っているか?
25
+ [https://stackoverflow.com/questions/34454531/java-how-can-i-generate-privatekey-from-a-string ](https://stackoverflow.com/questions/34454531/java-how-can-i-generate-privatekey-from-a-string)を参考に作成しました。
25
26
 
26
27
 
27
28
  ②[こちらのページ](https://developers.worksmobile.com/jp/reference/authorization-sa?lang=ja)のようなJWT署名をやりたい場合、 **秘密鍵を用いたJWT生成は以下のコードで合っているか?**

8

syuusei

2022/05/18 15:04

投稿

pp02
pp02

スコア4

test CHANGED
File without changes
test CHANGED
@@ -40,7 +40,7 @@
40
40
 
41
41
  ```Java
42
42
  //秘密鍵の設定
43
- String privateKey = {改行を除去した秘密鍵};
43
+ String privateKey = {"-----BEGIN PRIVATE KEY-----" と改行、"-----END PRIVATE KEY-----" を除去した秘密鍵};
44
44
 
45
45
  //ヘッダーの設定
46
46
  Map<String, Object> headerClaims = new HashMap();

7

syuusei

2022/05/18 14:07

投稿

pp02
pp02

スコア4

test CHANGED
File without changes
test CHANGED
@@ -53,6 +53,7 @@
53
53
  payloadClaims.put("iat", "JWT生成日時");
54
54
  payloadClaims.put("exp", "JWT満了日時");
55
55
 
56
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
56
57
  byte[] keyContentAsBytes = Base64.getDecoder().decode(privateKey);
57
58
  PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(keyContentAsBytes)
58
59
  //RSA256を用いた電子署名

6

しゅうせい

2022/05/18 13:50

投稿

pp02
pp02

スコア4

test CHANGED
File without changes
test CHANGED
@@ -58,7 +58,7 @@
58
58
  //RSA256を用いた電子署名
59
59
  try {
60
60
  RSAPrivateKey privKey = (RSAPrivateKey)keyFactory.generatePrivate(privSpec);
61
- Algorithm algorithm = Algorithm.RSA256(null, privateKey);
61
+ Algorithm algorithm = Algorithm.RSA256(null, privKey);
62
62
  String token = JWT.create()
63
63
     .withHeader(headerClaims)
64
64
     .withPayload(payloadClaims)

5

追記

2022/05/18 13:47

投稿

pp02
pp02

スコア4

test CHANGED
File without changes
test CHANGED
@@ -18,25 +18,17 @@
18
18
  ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-05-18/0007e21f-8c06-4158-baeb-123b08ee1c18.png)
19
19
 
20
20
  ### 発生している問題・エラーメッセージ
21
- java-jwt では、RSA256アルゴリズムで暗号化するためにはRSAPrivateKey型の秘密鍵を指定する必要があるのですが、秘密鍵を**String型の状態からどのようにしてRSAPrivateKey型に変換するかが分からない**状態です。また、公式の使用例だけではヘッダー情報とペイロード情報をどのようにして参照させるかが分からない状態す。そのめ、以下の2点を質問させてください
21
+ java-jwt では、RSA256アルゴリズムで暗号化するためにはRSAPrivateKey型の秘密鍵を指定する必要があるのですが、秘密鍵を**String型の状態からどのようにしてRSAPrivateKey型に変換するかが分からない**状態です。また、参考例だけではどのようにRS256によ電子署名を行うのかが具体的に理解することがきませんでした。
22
+ そのため、以下の2点を質問させてください。
22
23
 
23
- ①string型の秘密鍵を RSAPrivateKey型に変えること可能か?また変換すとしたらどのようにすか?
24
+ ①string型の秘密鍵を RSAPrivateKey型に変える方法「該当のソースコード」項目に記載してあるような方法で合っているか?
24
- ②[こちらのページ](https://developers.worksmobile.com/jp/reference/authorization-sa?lang=ja)の ヘッダーやペイロード情報を付与させるには以下のような記述で合っているか?
25
- ```Java
26
- Map<String, Object> headerClaims = new HashMap();
27
- //ヘッダーのalg と typ は自動で付与されるため何も書かない
28
25
 
29
- Map<String, Object> payloadClaims = new HashMap<>();
30
- payloadClaims.put("iss", "Client ID");
31
- payloadClaims.put("sub", "Service Account");
32
- payloadClaims.put("iat", "JWT生成日時");
33
- payloadClaims.put("exp", "JWT満了日時");
34
26
 
27
+ ②[こちらのページ](https://developers.worksmobile.com/jp/reference/authorization-sa?lang=ja)のようなJWT署名をやりたい場合、 **秘密鍵を用いたJWT生成は以下のコードで合っているか?**
28
+ (最終的なJWTとして、一応それっぽいものは生成されるのですが、Postmanを用いて確認すると「500 Internal Server Error」となり、正しいJWTではないことが予想されます)
29
+
35
- String token = JWT.create()
30
+ 一応、ヘッダーとペイロード情報は正常にBASE64エンコードできたことは確認済みです。
36
-    .withHeader(headerClaims)
31
+
37
-    .withPayload(payloadClaims)
38
- .sign(algorithm);
39
- ```
40
32
 
41
33
  ### 該当のソースコード
42
34
  gradleへのインポート
@@ -48,12 +40,7 @@
48
40
 
49
41
  ```Java
50
42
  //秘密鍵の設定
51
- String privateKey_string = "-----BEGIN PRIVATE KEY-----\n" +
43
+ String privateKey = {改行等を除去した秘密鍵};
52
- "wzLaxWoh... //中略 \n" +
53
- "-----END PRIVATE KEY-----";
54
-
55
- privateKey_string = //{privateKey_string} から改行や "-----BEGIN PRIVATE KEY-----" を適切に除去する ;
56
- RSAPrivateKey privateKey = //privateKey_string を RSAPrivateKey型に変換したい
57
44
 
58
45
  //ヘッダーの設定
59
46
  Map<String, Object> headerClaims = new HashMap();
@@ -66,17 +53,27 @@
66
53
  payloadClaims.put("iat", "JWT生成日時");
67
54
  payloadClaims.put("exp", "JWT満了日時");
68
55
 
56
+ byte[] keyContentAsBytes = Base64.getDecoder().decode(privateKey);
57
+ PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(keyContentAsBytes)
69
58
  //RSA256を用いた電子署名
70
59
  try {
60
+ RSAPrivateKey privKey = (RSAPrivateKey)keyFactory.generatePrivate(privSpec);
71
61
  Algorithm algorithm = Algorithm.RSA256(null, privateKey);
72
62
  String token = JWT.create()
73
63
     .withHeader(headerClaims)
74
64
     .withPayload(payloadClaims)
75
65
  .sign(algorithm);
66
+ System.out.println("JWT = " + token );
76
67
  } catch (JWTCreationException exception){
77
68
  //Invalid Signing configuration / Couldn't convert Claims.
78
69
  }
79
70
  ```
71
+ 実行結果は以下のようになってしまいます。
72
+ ・JWT自体はエラーが起きずに生成される
73
+ ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-05-18/c84fd76b-5bd9-4154-8785-8d008bed11b5.png)
74
+
75
+ ・200 OK が表示されない
76
+ ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-05-18/2c985f17-299c-4fae-8559-bb33fedb3d25.png)
80
77
  申し訳ありませんがどなたかご教授お願い致します。
81
78
 
82
79
  ### 試したこと

4

追記

2022/05/18 13:03

投稿

pp02
pp02

スコア4

test CHANGED
File without changes
test CHANGED
@@ -87,6 +87,7 @@
87
87
  ```
88
88
  ### 追記
89
89
  [こちらのサイト](https://tutorialmore.com/questions-2800307.htm)を参考に、以下のコードをJavaで実行すると正常に動作はするのですが、Postmanを使ってアクセストークンを取得しようとすると「500 Internal Sever Error」と表示されてしまいます。おそらく正しいJWTが取得できていないものだと思われます。
90
+ 本来の質問とはズレてしまうのですが、以下のコードでJWTを取得するためにはどこが間違っているのでしょうか?
90
91
  以下、使用コードです。
91
92
  ```Java
92
93
  import java.math.BigInteger;

3

追記

2022/05/18 12:53

投稿

pp02
pp02

スコア4

test CHANGED
File without changes
test CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  JavaでRS256アルゴリズムによるJWT電子署名を生成したいと考えています。
4
4
  現在、[java-jwt](https://github.com/auth0/java-jwt) を用いて実装しようとしています。
5
+
6
+ 手元には、
7
+ ・BASE64エンコードされたヘッダー情報
8
+ ・BASE64エンコードされたペイロード情報
9
+ ・JWT署名のために必要な秘密鍵
10
+ がすでに存在するという前提です。
5
11
 
6
12
  ### 前提
7
13
 

2

ttuiki

2022/05/18 12:51

投稿

pp02
pp02

スコア4

test CHANGED
File without changes
test CHANGED
@@ -79,7 +79,7 @@
79
79
  ```
80
80
  echo -n '{BASE64エンコードされたヘッダー}.{BASE64エンコードされたペイロード}' | openssl dgst -sha256 -sign privateKey.key -binary | base64
81
81
  ```
82
- ###追記
82
+ ### 追記
83
83
  [こちらのサイト](https://tutorialmore.com/questions-2800307.htm)を参考に、以下のコードをJavaで実行すると正常に動作はするのですが、Postmanを使ってアクセストークンを取得しようとすると「500 Internal Sever Error」と表示されてしまいます。おそらく正しいJWTが取得できていないものだと思われます。
84
84
  以下、使用コードです。
85
85
  ```Java
@@ -137,6 +137,8 @@
137
137
  }
138
138
  }
139
139
  ```
140
+ 実行結果
141
+ ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-05-18/6a6fea43-1f36-428c-b557-96b41d0bef0e.png)
140
142
 
141
143
  Postmanによる取得結果
142
144
  ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-05-18/be2899bc-0c12-49fe-b812-606cab3c8a11.png)

1

追記

2022/05/18 12:49

投稿

pp02
pp02

スコア4

test CHANGED
File without changes
test CHANGED
@@ -79,6 +79,65 @@
79
79
  ```
80
80
  echo -n '{BASE64エンコードされたヘッダー}.{BASE64エンコードされたペイロード}' | openssl dgst -sha256 -sign privateKey.key -binary | base64
81
81
  ```
82
+ ###追記
83
+ [こちらのサイト](https://tutorialmore.com/questions-2800307.htm)を参考に、以下のコードをJavaで実行すると正常に動作はするのですが、Postmanを使ってアクセストークンを取得しようとすると「500 Internal Sever Error」と表示されてしまいます。おそらく正しいJWTが取得できていないものだと思われます。
84
+ 以下、使用コードです。
85
+ ```Java
86
+ import java.math.BigInteger;
87
+ import java.util.Base64;
88
+ import java.security.KeyFactory;
89
+ import java.security.Signature;
90
+ import java.security.PrivateKey;
91
+ import java.security.SignatureException;
92
+ import java.security.NoSuchAlgorithmException;
93
+ import java.security.spec.RSAPrivateCrtKeySpec;
82
94
 
95
+ import java.security.InvalidKeyException;
96
+ import java.security.KeyFactory;
97
+ import java.security.NoSuchAlgorithmException;
98
+ import java.security.Signature;
99
+ import java.security.SignatureException;
100
+ import java.security.interfaces.RSAPrivateKey;
101
+ import java.security.spec.InvalidKeySpecException;
102
+ import java.security.spec.PKCS8EncodedKeySpec;
103
+
104
+ public class SHA256withRSA {
105
+ /**
106
+ * RSASSA-PKCS1-v1_5 with SHA-256によるデジタル署名の生成
107
+ */
108
+ public static void main(String args[]) throws Exception{
83
109
 
110
+ String header_local = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}";
111
+ String payload_local = "{\"iss\":\"{クライアントID}\",\"sub\":\"{サービスアカウントID}\",\"iat\":1652875817,\"exp\":1652878217}";
84
112
 
113
+ String headerEncoded = Base64.getEncoder().encodeToString(header_local.getBytes());
114
+ String payloadEncoded = Base64.getEncoder().encodeToString(payload_local.getBytes());
115
+
116
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
117
+ byte[] keyContentAsBytes = Base64.getDecoder().decode("{改行等を除去した秘密鍵本体}");
118
+ PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(keyContentAsBytes);
119
+
120
+ String tempAccessToken = headerEncoded+"."+ payloadEncoded;
121
+ try {
122
+ RSAPrivateKey privKey = (RSAPrivateKey)keyFactory.generatePrivate(privSpec);
123
+ Signature sign = Signature.getInstance("SHA256withRSA");
124
+ sign.initSign(privKey);
125
+ sign.update(tempAccessToken.getBytes());
126
+ byte[] signatureBytes = sign.sign();
127
+ String jsonToken = Base64.getUrlEncoder().encodeToString(signatureBytes);
128
+ String JWTtoken = tempAccessToken + "." + jsonToken;
129
+ System.out.println("JWT = " + JWTtoken);;
130
+ } catch (InvalidKeySpecException e) {
131
+ // TODO Auto-generated catch block
132
+ e.printStackTrace();
133
+ } catch (SignatureException e) {
134
+ // TODO Auto-generated catch block
135
+ e.printStackTrace();
136
+ }
137
+ }
138
+ }
139
+ ```
140
+
141
+ Postmanによる取得結果
142
+ ![イメージ説明](https://ddjkaamml8q8x.cloudfront.net/questions/2022-05-18/be2899bc-0c12-49fe-b812-606cab3c8a11.png)
143
+