-
-
Save njmube/b0afab9ccb6d3539eed7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Security.Cryptography; | |
using System.IO; | |
namespace RSASample | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
const int keysize = 1024; // 1024bit - 88bit = 117byte (最大平文サイズ) | |
// ※※※ マシンA, Bがあり、まずはAからはじまると想定する ※※※ | |
// 暗号化キーを安全に二点間で交換するためのRSA暗号化キーを生成する. | |
string keyPair; | |
byte[] publicModules; | |
byte[] publicExponent; | |
using (var rsa = new RSACryptoServiceProvider(keysize)) | |
{ | |
try | |
{ | |
// 秘密キー | |
keyPair = rsa.ToXmlString(true); | |
// 公開キー | |
RSAParameters publicParam = rsa.ExportParameters(false); | |
publicModules = publicParam.Modulus; | |
publicExponent = publicParam.Exponent; | |
// キーの表示 | |
Console.WriteLine("keyPair=" + keyPair); | |
Console.WriteLine("public(modules)=" + ToHexString(publicModules)); | |
Console.WriteLine("public(exponent)=" + ToHexString(publicExponent)); | |
} | |
finally | |
{ | |
// 生成したキーは保存しない. | |
rsa.PersistKeyInCsp = false; | |
rsa.Clear(); | |
} | |
} | |
// ※※※ ここでマシンBに公開キーを転送すると想定 ※※※ | |
// 共通暗号化のための、パスワードとソルト | |
var password = "Hello, World!!"; | |
byte[] salt = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; | |
// 共通暗号化キーをパスワードとソルトから生成する. | |
// JAVAの「PBKDF2WithHmacSHA1」相当. | |
var kf = new Rfc2898DeriveBytes(password, salt, 65536); | |
byte[] key = kf.GetBytes(128 / 8); // 128ビット長の秘密キーを生成 | |
// 公開キーで共通暗号キーを暗号化する. | |
byte[] encrypted; | |
using (var rsa = new RSACryptoServiceProvider()) | |
{ | |
try | |
{ | |
// エクスポートされたpublicキーを復元する. | |
var public2 = new RSAParameters(); | |
public2.Modulus = publicModules; | |
public2.Exponent = publicExponent; | |
rsa.ImportParameters(public2); | |
// RSA暗号化 | |
encrypted = rsa.Encrypt(key, false); // PKCS#1 v1.5 | |
} | |
finally | |
{ | |
rsa.PersistKeyInCsp = false; | |
rsa.Clear(); | |
} | |
} | |
// ※※※ ここでRSA暗号化された共通暗号化キーをマシンAに転送すると想定 ※※※ | |
// 秘密キーで共通暗号キーを復号化する. | |
byte[] key2; | |
using (var rsa = new RSACryptoServiceProvider()) | |
{ | |
try | |
{ | |
rsa.FromXmlString(keyPair); | |
key2 = rsa.Decrypt(encrypted, false); | |
} | |
finally | |
{ | |
rsa.PersistKeyInCsp = false; | |
rsa.Clear(); | |
} | |
} | |
// 復元された共通暗号化キーと、元のキーを表示する. (同じはず) | |
Console.WriteLine("key(org)=" + ToHexString(key)); | |
Console.WriteLine("key(dec)=" + ToHexString(key2)); | |
// 共通暗号化キーを用いてAES/CBC/PKCS7Paddingで長いデータを暗号化する. | |
byte[] iv; | |
byte[] encrypted2; | |
using (var aes = new AesCryptoServiceProvider()) | |
{ | |
aes.BlockSize = 128; | |
aes.KeySize = 128; | |
aes.Mode = CipherMode.CBC; | |
aes.Padding = PaddingMode.PKCS7; | |
//初期化ベクトルの設定と取得(ブロックサイズと同サイズ=128bit) | |
aes.GenerateIV(); | |
iv = aes.IV; | |
// 共通暗号化キーの設定 | |
aes.Key = key2; | |
// AES暗号化 | |
using (var encryptor = aes.CreateEncryptor()) | |
using (var memStm = new MemoryStream()) | |
{ | |
using (var cryptStm = new CryptoStream(memStm, encryptor, CryptoStreamMode.Write)) | |
{ | |
for (int idx = 0; idx < 1000; idx++) | |
{ | |
string mes = string.Format("({0,3:G}) ", idx); | |
byte[] data = Encoding.UTF8.GetBytes(mes); | |
cryptStm.Write(data, 0, data.Length); | |
} | |
} | |
encrypted2 = memStm.ToArray(); | |
} | |
} | |
// ※※※ ここでマシンBに、暗号化されたデータとIVを転送すると想定 ※※※ | |
// 共通暗号化キーと、IVを用いて、長いデータを復号化する | |
string ret; | |
using (var aes = new AesCryptoServiceProvider()) | |
{ | |
aes.BlockSize = 128; | |
aes.KeySize = 128; | |
aes.Mode = CipherMode.CBC; | |
aes.Padding = PaddingMode.PKCS7; | |
// 共通暗号化キーの設定 | |
aes.Key = key2; | |
// 初期ベクトルの設定 | |
aes.IV = iv; | |
// AES復号化 | |
using (var decryptor = aes.CreateDecryptor()) | |
using (var memStm = new MemoryStream(encrypted2)) | |
using (var memStm2 = new MemoryStream()) | |
{ | |
using (var cryptStm = new CryptoStream(memStm, decryptor, CryptoStreamMode.Read)) | |
{ | |
byte[] buf = new byte[1024]; | |
for (; ; ) | |
{ | |
int rd = cryptStm.Read(buf, 0, buf.Length); | |
if (rd <= 0) | |
{ | |
break; | |
} | |
memStm2.Write(buf, 0, rd); | |
} | |
} | |
byte[] data = memStm2.ToArray(); | |
ret = Encoding.UTF8.GetString(data); | |
} | |
} | |
// マシンAからマシンBに転送されたデータを表示する. | |
Console.WriteLine("ret=" + ret); | |
} | |
/// <summary> | |
/// バイト列を16進数文字列に変換する. | |
/// </summary> | |
/// <param name="data"></param> | |
/// <returns></returns> | |
private static string ToHexString(byte[] data) | |
{ | |
var buf = new StringBuilder(); | |
foreach (byte d in data) | |
{ | |
buf.Append(d.ToString("x2")); | |
} | |
return buf.ToString(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment