共通鍵暗号方式では、鍵を通信相手へ秘密裏に配信する必要がありますが、
安全に送ることが困難です。
途中で、漏洩したかどうか分かりません。
また、複数の人で互いに秘密通信をしようとした場合、鍵の管理が大変となります。
例えば、2人であれば、1つの鍵を共有します。
3人であれば、全体として3個の鍵が必要です。
4人であれば、3+2+1=6個の鍵が必要です。
5人であれば、4+3+2+1=6個の鍵が必要です。
N人で行う場合、1+2+3+4+・・+N=1/2×N×(N-1)の鍵が必要です。
人数が増えるごとに増大します。しかもいくら自分が注意しても、
一方で鍵を紛失したり、漏洩すると、暗号が解読される危険があります。
その対策として、次の公開鍵暗号方式が生まれました。
公開鍵暗号方式は非対称鍵を使う方式です。
鍵を作る時「公開鍵」と「秘密鍵」の二つが同時に作られます。
そして、「公開鍵」の方を、見られても構わない鍵として使います。
(文字通り公開して使うこともあります。)
そして、秘密鍵は盗まれたり、見られたりできなないよう厳重に管理します。
この対になるキーには『一方で暗号化したものは、
もう一方のキーを使わなければ復号できない』性質があります。
よって、使い方は次の2通りあります。(秘密キーは必ず手元にあります)
『公開キーで暗号化し、秘密キーで復号する』
相手の公開キーで平文を暗号化し、平文が相手以外に漏れるのを防ぐ。
『秘密キーで暗号化し、公開キーで復号する』
自分の秘密キーで平文を暗号化して、改ざんや成りすましを防ぐ。
(復号側では暗号者の公開キーを間違いなく取得する必要がある。)
RSAの公開鍵暗号方式プログラムを以下に示します。
なお、このRSA(R.Rivest, A.Shamir & L.Adleman:リベスト,シャミア,エーデルマンによって1977年に発明)の
公開鍵方式の暗号のしくみは
『非常に大きな整数の素因数分解は極めて困難』という
整数の性質に基づいています。
以下のソースをコピーして、RSA.htaの名前で保存して実験ください。
これで私の公開キー が作成してあります
←右ボタンでダウンロード
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<style type="text/css">
p, input { font-size: 12pt; font-family: monospace; }
</style>
<script language="javascript">
// ADODB.Stream
var adTypeBinary = 1;
var adTypeText = 2;
var adSaveCreateNotExist = 1;
var adSaveCreateOverWrite = 2;
var adReadAll = -1;
var adReadLine = -2;
//------------------------
var csUnicode = "unicode";
var csUTF8 = "utf-8";
var csJIS = "iso-2022-jp";
var csShiftJIS = "Shift_JIS";
var csEUCJP = "euc-jp";
var doc = document;
// ===========================================
//公開鍵と、秘密鍵のペアを生成
// ===========================================
function CreateKeys(){
var user_id = doc.getElementById("usrId").value;
var objCrypt = new ActiveXObject("System.Security.Cryptography.RSACryptoServiceProvider");
var publicKey = objCrypt.ToXmlString(false);//公開鍵をXML形式で取得
var privateKey = objCrypt.ToXmlString(true);//秘密鍵をXML形式で取得
var fso = new ActiveXObject("Scripting.FileSystemObject");
if( fso.FileExists("privateKey.xml") ) {
alert("privateKey.xmlがすでに存在します。\nこの秘密鍵とその公開鍵を、名前を変えるか削除ください。");
return;
}
//公開鍵をXML形式でファイル化
var textObj1 = fso.OpenTextFile(user_id + "_publicKey.xml", 2, true);
textObj1.Write(publicKey);
textObj1.Close();
//秘密鍵をXML形式でファイル化
var textObj2 = fso.OpenTextFile("privateKey.xml", 2, true);
textObj2.Write(privateKey);
textObj2.Close();
}
// =================================================
//公開鍵で、指定のファイルをxmlファイルに暗号化する。
// =================================================
function usePublic(){
//●公開鍵をファイルから読み取り、「objCrypt」にセット
var key_file = doc.getElementById("keyFile").value;
if(key_file == "") {
alert("公開鍵のファイルを指定ください。");
return;
}
var fso = new ActiveXObject("Scripting.FileSystemObject");
var tsKey = fso.OpenTextFile(key_file, 1, true);
var strXML = tsKey.ReadAll();
var objCrypt = new ActiveXObject("System.Security.Cryptography.RSACryptoServiceProvider");
//alert(strXML);
objCrypt.FromXmlString(strXML);
tsKey.Close();
//●暗号対象ファイルを読み取り、byte配列「binValue」に記憶
var src_file = doc.getElementById("srcFile").value;
if(src_file == "") {
alert("復号するファイルを指定ください。");
return;
}
if(fso.GetFile(src_file).Size >= 100){
alert("暗号するファイルのサイズが" + fso.GetFile(src_file).Size +"byteです。\n100byte以内にしてください。");
return;
}
var objStream = new ActiveXObject("ADODB.Stream");
objStream.open();
objStream.Position = 0;
objStream.Type = adTypeBinary;
objStream.loadFromFile(src_file);
var binValue = objStream.Read(adReadAll);
objStream.Close();
//alert( binValue );
//●byte配列「binValue」を暗号化してにbyte配列「binDecryptValue」記憶
var binEncryptValue = objCrypt.Encrypt(binValue, false);
//●暗号化しされたbyte配列「binDecryptValue」で、XMLファイル作成
var document = new ActiveXObject( "MSXML2.DOMDocument" ) ;
var root = document.createElement( "base64" ) ;
root.setAttribute( "name", "RSAEncrypt" ) ;
document.documentElement = root ;
var temp = document.createElement( "temp" ) ;
temp.dataType = "bin.base64" ;
temp.nodeTypedValue = binEncryptValue ;
root.text = temp.text.replace( /\r\n|\r|\n/g, "" ) ;
src_file = src_file + "public_encrypt.xml";
document.save( src_file );
alert(src_file + "\nのファイルへ暗号化しました。");
}
// ===========================================
//秘密鍵で、暗号化されたxmlファイルを復号する。
// ===========================================
function usePrivate(){
//●秘密鍵をファイルから読み取り、「objCrypt」にセット
var fso = new ActiveXObject("Scripting.FileSystemObject");
if( ! fso.FileExists("privateKey.xml") ) {
alert("privateKey.xmlのファイルが見つかりません。");
return;
}
var tsKey = fso.OpenTextFile("privateKey.xml", 1, true);
strXML = tsKey.ReadAll();
var objCrypt = new ActiveXObject("System.Security.Cryptography.RSACryptoServiceProvider");
objCrypt.FromXmlString(strXML);
//●暗号化されたXMLファイル「enc_file」を読み取ったbyte配列を、「binEncryptValue」に記憶
var enc_file = doc.getElementById("encFile").value;
if(enc_file == "") {
alert("復号するファイルを指定ください。");
return;
}
var document = new ActiveXObject( "MSXML2.DOMDocument" ) ;
if ( !document.load( enc_file ) ) {
alert("見つかりません") ;
}
var root = document.documentElement ;
var name = root.getAttribute( "name" ) ;
var temp = document.createElement( "temp" ) ;
temp.dataType = "bin.base64" ;
temp.text = root.text ;
binEncryptValue=temp.nodeTypedValue;
//●暗号化されたbyte配列「binEncryptValue」を、復号して「binDecryptValue」に記憶
binDecryptValue = objCrypt.Decrypt(binEncryptValue, false);
//alert(binDecryptValue);
//●復号した「binDecryptValue」のbyte配列をファイルに保存
var objStream = new ActiveXObject("ADODB.Stream");
objStream.open();
objStream.Type = adTypeBinary;
objStream.Write(binDecryptValue);
objStream.SaveToFile( enc_file + ".txt", adSaveCreateOverWrite );
objStream.Close();
alert( enc_file + ".txtのファイルに復号しました。" );
}
</script>
</head>
<body>
<p>ユーザーID
<input type="text" id="usrId" size="10">
<input type="button" value="公開鍵と、秘密鍵のペアを生成" onclick="CreateKeys()">
</p>
<hr><!-- ===================================================== -->
<p>使用する公開鍵<input type="file" size="60" id="keyFile"><br>
暗号化するFile<input type="file" size="60" id="srcFile"><br>
<input type="button" value="公開鍵を使う" onclick="usePublic()">
</p>
<hr><!-- ===================================================== -->
<p>復号するFile<input type="file" id="encFile" size="60"><br>
<input type="button" value="秘密鍵を使う" onclick="usePrivate()">
</p>
使っているActiveXのドキュメント<br>
<a href="http://msdn.microsoft.com/ja-jp/library/cc409798.aspx" target="FileSystemObject">
FileSystemObject参照</a><br>
<a href="http://msdn.microsoft.com/ja-jp/library/cc408235.aspx" target="ADO">
ADO参考</a><br>
<a href="http://msdn.microsoft.com/ja-jp/library/system.security.cryptography.rsacryptoserviceprovider(VS.80).aspx">
RSA参考</a><br>
<a href="http://msdn.microsoft.com/ja-jp/library/ms256465.aspx" target="MSXML">
MSXML2.DOMDocument参照</a><br>(MSXMLは、Internet Explorer の一部として提供される)
</body>
</html>