RAS暗号化、復号

RSAの公開キーと秘密キーを生成し、
plain_message = "12345\nABCあいえお";の平文を公開鍵で暗号化しています。
これを、秘密キーで復号化して、表示しています。

import java.security.*;
import java.security.interfaces.*;//RSAPublicKey, RSAPrivateKey
import java.math.BigInteger;

class RSA{

	static final char[] B64 = { //変換に使うテーブル 64進(6bit分)を  16桁 4行で表現している 
	'A' ,'B' ,'C' ,'D' ,'E' ,'F' ,'G' ,'H' ,'I' ,'J' ,'K' ,'L' ,'M' ,'N' ,'O' ,'P',//00〜0Fの64進に対応する文字
	'Q' ,'R' ,'S' ,'T' ,'U' ,'V' ,'W' ,'X' ,'Y' ,'Z' ,'a' ,'b' ,'c' ,'d' ,'e' ,'f',//10〜1Fの64進対応に対応する文字
	'g' ,'h' ,'i' ,'j' ,'k' ,'l' ,'m' ,'n' ,'o' ,'p' ,'q' ,'r' ,'s' ,'t' ,'u' ,'v',//20〜2Fの64進対応に対応する文字
	'w' ,'x' ,'y' ,'z' ,'0' ,'1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,'8' ,'9' ,'+' ,'/' //30〜3Fの64進対応に対応する文字
	};

	//引数のbyte配列を、Base64の文字列に変換して返す。
	public static String encode64(byte a[])
	{
		if (a.length == 0) return "";
		StringBuffer s = new StringBuffer();//変換した文字列記憶用
		int cnt3 = 0;	//3yteカウント用
		long data = 0;	//変換対象用:3byteを設定し、4文字で取り出す
		int idx = 0;
		do
		{
			//data に 3byte分を設定
			data <<= 8;
			if (idx < a.length)
			{
				if (a[idx] >= 0)
				{//Javaは符号なしがないので、if文で処理を変える
					data += a[idx];
				}
				else
				{
					data += 256 + a[idx]; //符号なしのコードに変換して加算
				}
			}
			cnt3++;
			if (cnt3 == 3)
			{//3byteごとに変換

				//dataを4個の64進に対応する文字に変換
				int i = (int)(data / (64 * 64 * 64));
				//System.out.println(data + "," + i + "," + 256 * 256 * 256);
				s.append(B64[i]);//1文字目

				data = data % (64 * 64 * 64);
				i = (int)(data / (64 * 64));
				s.append(B64[i]);//2文字目

				data = data % (64 * 64);
				i = (int)(data / (64));
				s.append(B64[i]);//3文字目

				data = data % 64;
				s.append(B64[(int)data]);//4文字目

				data = 0;	//次の変換データの準備
				cnt3 = 0;
			}
			idx++;
		} while (idx < a.length || cnt3 != 0);
		int len = s.length(); //文字列の長さ
		String rtnval = "";
		if (a.length % 3 == 2)
		{
			return s.substring(0, len - 1) + "=";
		}
		else if (a.length % 3 == 1)
		{
			return s.substring(0, len - 2) + "==";
		}
		else
		{
			return s.toString();
		}
	}

	//Base64の文字列から、バイナリデータを求める。
	public static byte[] decode64(String s)
	{
		int n = s.length() * 3 / 4;
		if (s.endsWith("==")) n -= 2;
		else if (s.endsWith("=")) n -= 1;
		byte[] bi = new byte[n];
		int iset = 0;
		int len = s.length();
		int data = 0;
		int icount = 0;
		int i;
		try
		{
			for (i = 0; i < len; i++)
			{ //文字を順番に処理する。
				char c = s.charAt(i);
				data <<= 6;// 6ビットシフト
				icount++;
				if (c != '=')
				{
					//Base64の文字から、テーブル内のインデックスを求める。
					if (c >= 'A' && c <= 'Z')
					{
						data |= c - 'A';
					}
					else if (c >= 'a' && c <= 'z')
					{
						data |= c - 'a' + 0x1a;
					}
					else if (c >= '0' && c <= '9')
					{
						data |= c - '0' + 0x34;
					}
					else if (c == '+')
					{
						data |= 0x3e;
					}
					else if (c == '/')
					{
						data |= 0x3f;
					}
				}
				if (icount == 4)
				{
					icount = 0;
					bi[iset++] = (byte)((data >> 16) & 0x00ff);
					bi[iset++] = (byte)((data >> 8) & 0x00ff);
					bi[iset++] = (byte)(data & 0x00ff);
					data = 0;
				}
			}
		}
		catch (ArrayIndexOutOfBoundsException e)
		{
			//  =文字など無効なデータ分の設定は無視 
			//System.out.println( iset + "::::" + e.toString());
		}
		return bi;
	}


	public static void main(String arg[]) throws Exception
	{
		// キーペアの生成
		KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
		SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
		generator.initialize(1024, random);
		KeyPair keyPair = generator.generateKeyPair();

		// 秘密鍵・公開鍵の取得
		RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
		RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();

		//平文
		String plain_message = "12345\nABCあいえお";
		System.out.print("平文『");
		System.out.println(plain_message+"』");

		//暗号化 plain_messageを暗号化して、enCodeNumに記憶
		BigInteger exponentP = publicKey.getPublicExponent();
		BigInteger modulusP = publicKey.getModulus();
		BigInteger msg = new BigInteger( plain_message.getBytes() );
		BigInteger enCodeNum = msg.modPow(exponentP, modulusP);
		System.out.print("\n公開鍵で暗号化したコード『");
		System.out.println(encode64(enCodeNum.toByteArray())+"』");

		//復号 enCodeNum を復号して、deCodeNumに記憶
		BigInteger exponentS = privateKey.getPrivateExponent();
		BigInteger modulusS = privateKey.getModulus();
		BigInteger deCodeNum = enCodeNum.modPow(exponentS, modulusS);
		System.out.print("\n秘密鍵で復号したコード『");
		System.out.println(new String(deCodeNum.toByteArray()) + "』");
	}
}