共通鍵暗号方式では、鍵を通信相手へ秘密裏に配信する必要がありますが、
安全に送ることが困難です。
途中で、漏洩したかどうか分かりません。
また、複数の人で互いに秘密通信をしようとした場合、鍵の管理が大変となります。
例えば、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>