実現したいこと
Yahooショッピング 注文APIにて、「公開鍵で暗号化した認証情報をAPIリクエストヘッダに付加してリクエスト」をVB.NETにて実装
認証手順
1.公開鍵ファイルを作成
公開鍵の内容はYahooショッピング管理コンソールにて発行
内容をコピーし、public.keyというファイル名でファイル作成
<公開鍵内容例>
-----BEGIN PUBLIC KEY-----
ABCfMA0GCSqGSIb...6txJ/YUbwIDACBA
-----END PUBLIC KEY-----
2.認証情報の作成
ストアアカウントとunixtimestampを:で結合した情報を作成
3.認証情報を公開鍵で暗号化
認証情報を公開鍵で暗号化(PKCS1PADDING)し、BASE64エンコード
4.暗号化した認証情報をAPIリクエストヘッダに付加してリクエスト
前提
・認証情報がなくてもエラーとはならない。
・APIリクエスト・レスポンスは、認証なしでも問題なくできている。
発生している問題・エラーメッセージ
・下記のコードを実行した場合、
レスポンスヘッダー取得「X-SWS-Authorize-Status」にて、「unauthorized」のレスポンスが返る。
※成功すれば、「authorized」が返る
該当のソースコード
VB.NET
1 ' UTF-8でエンコードする 2 Dim enc As Encoding = New UTF8Encoding() 3 4 'WebAPI暗号鍵処理 5 'ストアクリエイターPro上で発行した公開鍵のパス 6 Dim keyFilePath As String = String.Format("{0}/key/{1}", sCurrentDir, PUBLICKEYFILENM) 7 8 '現在日時取得(unixtimestamp取得) 9 Dim unixTime As Long = GetUnixTime(DateTime.Now) 10 ⇒GetUnixTimeメソッドは最下部に記載 11 12 '認証情報作成(ストアアカウントとunixtimestampを:で結合する) 13 Dim authenticationValue As String = String.Format("{0}:{1}", STOREACCOUNT, unixTime) 14 15 'pem形式の公開鍵読み込み 16 '読み込むファイル 17 Dim textFile As String = keyFilePath 18 'テキストファイルの中身をすべて読み込む 19 Dim publicKeyPem As String = System.IO.File.ReadAllText(textFile, enc) 20 21 '不要部分を削除 22 publicKeyPem = Replace(publicKeyPem, "-----BEGIN PUBLIC KEY-----" & vbCrLf, String.Empty) 23 publicKeyPem = Replace(publicKeyPem, "-----END PUBLIC KEY-----", String.Empty) 24 publicKeyPem = Replace(publicKeyPem, vbLf, String.Empty) 25 26 '公開鍵と秘密鍵を取得 27 Dim privateKey As String = publicKeyPem 28 Dim publicKey As String = publicKeyPem 29 CreateKeys(PublicKey, privateKey) 30 ⇒CreateKeysメソッドは最下部に記載 31 32 '認証情報の暗号化 33 Dim encodedAuthenticationValue As String = Encrypt(authenticationValue, publicKey) 34 ⇒Encryptメソッドは最下部に記載 35 36 'POST送信する文字列を作成 37 Dim postData As String = _ 38 GetRequestXMLData_OrderList(iGetOrderMaxCnt, sIsSeen, Format(Now.AddDays(-iOrderGetPeriod), "yyyyMMddHHmmss"), Format(Now, "yyyyMMddHHmmss"), "1,2", STOREACCOUNT) 39 ⇒GetRequestXMLData_OrderListメソッドは今回の問題点とは関係ないため未記載 40 41 'バイト型配列に変換 42 Dim postDataBytes As Byte() = _ 43 System.Text.Encoding.UTF8.GetBytes(postData) 44 45 'TLS1.2での通信対応 46 ServicePointManager.SecurityProtocol = DirectCast(3072, SecurityProtocolType) 47 48 'WebRequestの作成 49 Dim req As System.Net.HttpWebRequest = _ 50 System.Net.HttpWebRequest.Create(YAHOOAPI_ORDERLISTURL) 51 52 'アクセストークン取得 53 sAccessToken = Get_AccessToken() 54 ⇒Get_AccessTokenメソッドは今回の問題点とは関係ないため未記載 55 56 'ヘッダ指定 57 req.Headers.Add("Authorization: Bearer " & sAccessToken) 58 req.Headers.Add("X-sws-signature: " & encodedAuthenticationValue) '暗号化した認証情報 59 req.Headers.Add("X-sws-signature-version: 1") '取得した公開鍵のバージョン 60 61 'メソッドにPOSTを指定 62 req.Method = "POST" 63 'ContentTypeを"application/x-www-form-urlencoded"にする 64 req.ContentType = "application/x-www-form-urlencoded" 65 66 'POST送信するデータの長さを指定 67 req.ContentLength = postDataBytes.Length 68 69 'データをPOST送信するためのStreamを取得 70 Dim reqStream As System.IO.Stream = req.GetRequestStream() 71 '送信するデータを書き込む 72 reqStream.Write(postDataBytes, 0, postDataBytes.Length) 73 reqStream.Close() 74 75 'サーバーからの応答を受信するためのWebResponseを取得 76 Dim res As System.Net.HttpWebResponse = req.GetResponse() 77 'レスポンスヘッダー取得「X-SWS-Authorize-Status」 78 For i As Integer = 0 To res.Headers.Count - 1 79 If res.Headers.Keys(i) = "X-Sws-Authorize-Status" Then 80 If res.Headers(i) <> "authorized" Then 81 'エラー 82 End If 83 Exit For 84 End If 85 Next 86 87 '応答データを受信するためのStreamを取得 88 Dim resStream As System.IO.Stream = res.GetResponseStream() 89 '受信して表示 90 Dim sr As New System.IO.StreamReader(resStream, enc) 91 Dim sInfo As String = sr.ReadToEnd() 92 93 '閉じる 94 sr.Close() 95 96 ''' <summary> 97 ''' UNIXTIMESTAMP取得 98 ''' </summary> 99 ''' <param name="targetTime"></param> 100 ''' <returns></returns> 101 ''' <remarks></remarks> 102 Public Shared Function GetUnixTime(ByVal targetTime As DateTime) As Long 103 ' UNIXエポックを表すDateTimeオブジェクトを取得 104 Dim UNIX_EPOCH As DateTime = New DateTime(1970, 1, 1, 0, 0, 0, 0) 105 106 ' UTC時間に変換 107 targetTime = targetTime.ToUniversalTime() 108 109 ' UNIXエポックからの経過時間を取得 110 Dim elapsedTime As TimeSpan = targetTime - UNIX_EPOCH 111 112 ' 経過秒数に変換 113 Return CType(elapsedTime.TotalSeconds, Long) 114 115 End Function 116 117 ''' <summary> 118 ''' 公開鍵と秘密鍵を作成して返す 119 ''' </summary> 120 ''' <param name="publicKey">作成された公開鍵(XML形式)</param> 121 ''' <param name="privateKey">作成された秘密鍵(XML形式)</param> 122 Public Shared Sub CreateKeys(ByRef publicKey As String, _ 123 ByRef privateKey As String) 124 'RSACryptoServiceProviderオブジェクトの作成 125 Dim rsa As New System.Security.Cryptography.RSACryptoServiceProvider() 126 127 '公開鍵をXML形式で取得 128 publicKey = rsa.ToXmlString(False) 129 '秘密鍵をXML形式で取得 130 privateKey = rsa.ToXmlString(True) 131 End Sub 132 133 ''' <summary> 134 ''' 公開鍵を使って文字列を暗号化する 135 ''' </summary> 136 ''' <param name="str">暗号化する文字列</param> 137 ''' <param name="publicKey">暗号化に使用する公開鍵(XML形式)</param> 138 ''' <returns>暗号化された文字列</returns> 139 Public Shared Function Encrypt(ByVal str As String, _ 140 ByVal publicKey As String) As String 141 'RSACryptoServiceProviderオブジェクトの作成 142 Dim rsa As New System.Security.Cryptography.RSACryptoServiceProvider() 143 144 '公開鍵を指定 145 rsa.FromXmlString(publicKey) 146 147 '暗号化する文字列をバイト配列に 148 Dim data As Byte() = System.Text.Encoding.UTF8.GetBytes(str) 149 '暗号化する 150 '(XP以降の場合のみ2項目にTrueを指定し、OAEPパディングを使用できる) 151 Dim encryptedData As Byte() = rsa.Encrypt(data, False) 152 153 'Base64で結果を文字列に変換 154 Return System.Convert.ToBase64String(encryptedData) 155 End Function
様々なサイトを参考にしましたが、手詰まり状態です。
お気づきの点等ありましたらご指摘・ご教授頂けるとありがたいです。
※VB.NETは”.Net Framework4.0”を使用
参考サイト
回答2件
あなたの回答
tips
プレビュー