前提
プログラマ1年目の初心者です。至らない点や認識の間違いなどあるかと思いますが、どうかよろしくお願いいたします。
JWT(Json Web Token)発行を実装したいのですが、発行はしているが、正しい署名情報でないためか、認証失敗してしまいます。
調べましたが、情報が乏しいため、こちらに質問させていただくに至りました。
ES256形式(curve : P-256 (secp256r1),hash Algorithm : SHA-256)による実装です。
実現したいこと
- JWTの鍵による認証を成功させたい
発生している問題・エラーメッセージ
下記認証サイトによるInvailed Signatureエラー
https://jwt.io/
該当のソースコード
C#
1using System; 2using System.Linq; 3using System.Text; 4using System.Windows.Forms; 5using System.Text.Json; 6using System.IO; 7using Org.BouncyCastle.Crypto; 8using Org.BouncyCastle.OpenSsl; 9using Org.BouncyCastle.Crypto.Signers; 10 11namespace WindowsFormsApp1 12{ 13 public partial class Form1 : Form 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 20 private static string plainText; 21 private static string key; 22 private static byte[] signature; 23 24 /// <summary> 25 /// ボタンクリックイベント(main) 26 /// </summary> 27 /// <param name="sender"></param> 28 /// <param name="e"></param> 29 private void ConfirmButton_Click(object sender, EventArgs e) 30 { 31 // generate token 32 string token = GenerateJwtToken(); 33 34 // output token 35 Console.WriteLine(token); 36 } 37 38 /// <summary> 39 /// Jwtトークンの生成 40 /// </summary> 41 /// <param name="privateKey"></param> 42 /// <returns></returns> 43 public static string GenerateJwtToken() 44 { 45 var header = new Header() 46 { 47 Typ = "JWT", 48 Kid = "kid", 49 Alg = "ES256" 50 }; 51 52 var payload = new Payload() 53 { 54 Name = "name" 55 }; 56 57 // header,payload確認 58 var jsonHeader = JsonSerializer.Serialize(header); 59 var jsonPayload = JsonSerializer.Serialize(payload); 60 string encodedHeader = Convert.ToBase64String(Encoding.UTF8.GetBytes(jsonHeader)).TrimEnd('=').Replace('+', '-').Replace('/', '_'); 61 string encodedPayload = Convert.ToBase64String(Encoding.UTF8.GetBytes(jsonPayload)).TrimEnd('=').Replace('+', '-').Replace('/', '_'); 62 63 // token発行 64 plainText = encodedHeader + "." + encodedPayload; 65 key = @"C:\~~~\prime256v1.privatekey"; 66 signature = Sign(plainText, key); 67 string encodedSignature = Convert.ToBase64String(signature).TrimEnd('=').Replace('+', '-').Replace('/', '_'); 68 string token = encodedHeader + "." + encodedPayload + "." + encodedSignature; 69 70 return token; 71 } 72 73 /// <summary> 74 /// 署名する 75 /// </summary> 76 static byte[] Sign(string clearText, string key) 77 { 78 var plain = Encoding.UTF8.GetBytes(clearText); 79 80 // 鍵を読み込む 81 AsymmetricCipherKeyPair pair = null; 82 using (var stream = new StreamReader(key)) 83 { 84 var reader = new PemReader(stream); 85 pair = reader.ReadObject() as AsymmetricCipherKeyPair; 86 } 87 88 // 署名インスタンスを生成&署名 89 var signer = new ECDsaSigner(); 90 signer.Init(true, pair.Private); 91 var sign = signer.GenerateSignature(plain); 92 93 // 署名の値をbyte[]にしておく 94 var sign1 = sign[0].ToByteArray().SkipWhile(b => b == 0x00).Reverse(); 95 var sign2 = sign[1].ToByteArray().SkipWhile(b => b == 0x00).Reverse(); 96 byte[] signature = sign1.Concat(sign2).ToArray(); 97 98 return signature; 99 } 100 101 102 /// <summary> 103 /// ヘッダー格納用クラス 104 /// </summary> 105 public class Header 106 { 107 public string Typ { get; set; } 108 public string Kid { get; set; } 109 public string Alg { get; set; } 110 } 111 112 /// <summary> 113 /// ペイロード格納用クラス 114 /// </summary> 115 public class Payload 116 { 117 public string Name { get; set; } 118 } 119 120 } 121}
試したこと
大参考記事 https://qiita.com/rawr/items/1a11edf694f550596879
①opensslで鍵ペアを作成
②(①を取り込んだ)C#を実行し、JWTを生成
③ ①と②を https://jwt.io/ に入力し、認証
②の署名作成部分(Sign())が間違っているのではないかと思ったのですが、調べても同じような実装例が見つからず、解決できませんでした。
参考記事の認証メソッドVerifyも実装しました。メソッドでは認証が成功しましたが、認証サイトでは認証が成功しませんでした。
補足情報(FW/ツールのバージョンなど)
Windows10
Visual studio 2019
.NET Framework 4.7.2
BouncyCastle 1.8.9(VS2019インストール時にすでにインストール済)
OpenSSL 1.1.1s 1 Nov 2022
openssl実行コマンド:
$ openssl ecparam -genkey -name prime256v1 -out prime256v1.keypair
$ openssl ec -in prime256v1.keypair -outform PEM -out prime256v1.privatekey
$ openssl ec -in prime256v1.keypair -outform PEM -pubout -out prime256v1.publickey




回答1件
あなたの回答
tips
プレビュー