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