Skip to content

Instantly share code, notes, and snippets.

@njmube
Forked from seraphy/RSASample.cs
Last active August 29, 2015 14:23
Show Gist options
  • Save njmube/4a00a3a248f0d5e21c20 to your computer and use it in GitHub Desktop.
Save njmube/4a00a3a248f0d5e21c20 to your computer and use it in GitHub Desktop.
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