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()) + "』");
}
}