質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.44%
HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Q&A

解決済

1回答

5469閲覧

RSACryptoServiceProviderによる鍵生成とBase64エンコーディングについて

Clor

総合スコア883

HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

0グッド

0クリップ

投稿2016/12/02 04:39

C#とJavaによる共通鍵交換を学習しています。

作成しているプログラムは以下の流れで処理したいと考えています。
①クライアント(C#)でRSAキーペアを生成する
②クライアントからサーバ(Java, SpringMVC)へBase64でエンコードした公開鍵をPOSTする
③サーバで共通鍵を生成し、受け取った公開鍵を利用して共通鍵を暗号化しクライアントにレスする

【クライアントサイド】

C#

1static void Main(string[] args) { 2 // RSAキーペアを生成 3 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); 4 // 公開鍵を取り出してBase64でエンコード 5 String encPublicKey = Convert.ToBase64String(rsa.ExportCspBlob(false)); 6 Console.WriteLine(encPublicKey); // デバッグのためコンソール出力 7 // エンコードした公開鍵をパラメータにしてサーバへPOST 8 String url = "http://localhost/rsasample/"; 9 String param = ""; 10 var dic = new Dictionary<String, String>(); 11 dic["key"] = encPublicKey; 12 foreach (String key in dic.Keys) { 13 param += String.Format("{0}={1}&", key, dic[key]); 14 } 15 byte[] data = Encoding.UTF8.GetBytes(param); 16 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 17 request.Method = "POST"; 18 request.ContentType = "application/x-www-form-urlencoded"; 19 request.ContentLength = data.Length; 20 using (Stream reqStream = request.GetRequestStream()) 21 reqStream.Write(data, 0, data.Length); 22 23 // 以下返ってきた共通鍵を復号する処理へ 24}

【サーバサイド】

Java

1@RequestMapping(value = "/rsasample/", method = RequestMethod.POST) 2@ResponseBody 3public String rsasample(@RequestParam String key) { 4 Log.info(key); // Base64エンコード文字列を確認するためログ出力 5 byte[] decodeKey = Base64.getDecoder().decode(key); 6 7 // 以下受け取った公開鍵で共通鍵を暗号化してレスポンスする処理へ 8}

上記プログラム実行時にサーバサイドで受け取ったkeyをdecodeすると以下のエラーが発生します。
java.lang.IllegalArgumentException: Illegal base64 character 20
at java.util.Base64$Decoder.decode0(Unknown Source)
at java.util.Base64$Decoder.decode(Unknown Source)
at java.util.Base64$Decoder.decode(Unknown Source)

ちなみにクライアントサイドで以下のように文字列をBase64エンコードして送った場合はサーバサイドでも正常にBase64デコードすることができました。

C#

1// String encPublicKey = Convert.ToBase64String(rsa.ExportCspBlob(false)); 2String encPublicKey = Convert.ToBase64String(Encoding.UTF8.GetBytes("あいうえお"));

またソースファイルの文字コードはC#, JavaともにUTF-8となっています。
怪しい点等ご教授いただければ幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

coco_bauer

2016/12/02 05:15

"Illegal base64 character 20"の20がスペース(ASCIIで文字コードが0x20)を意味するのだとすれば、どこかで余分なスペースを入れていないか確認してみることをお勧めします。
Clor

2016/12/02 05:37

ご回答ありがとうございます。まさにその通りでした。
guest

回答1

0

自己解決

coco_bauer様のご指摘通り、Java側でdecode()する際の文字列に半角スペースが入っていました。
Base64エンコードした文字列の+が受け取りの際に半角スペースに置き換えられていたためでした。
強引かもしれませんがJava側で半角スペースを+にreplaceAll()してからdecode()すると正常動作となりました。

投稿2016/12/02 05:40

Clor

総合スコア883

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.44%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問