?? crsa.java
字號:
e.printStackTrace();
return 0;
}
}
// 最大輸入長度
private int getInputBlockSize(boolean forEncryption)
{
int bitSize = pukParam.getModulus().bitLength();
if (forEncryption)
{
return (bitSize + 7) / 8 - 1;
}
else
{
return (bitSize + 7) / 8;
}
}
// 最大的輸出長度
private int getOutputBlockSize(boolean forEncryption)
{
int bitSize =
pukParam.getModulus().bitLength();
if (forEncryption)
{
return (bitSize + 7) / 8;
}
else
{
return (bitSize + 7) / 8 - 1;
}
}
// 密鑰對的生成
public int generateKeyPair(int length)
{
BigInteger p, q, n, d, e, pSub1, qSub1, phi;
BigInteger dP, dQ, qInv;
int pbitlength = (length + 1) / 2;
int qbitlength = (length- pbitlength);
//e在標準中推薦使用3或65537
e=new BigInteger("65537",10);
//生成素數p,并且使p-1與e互素
for (;;)
{
p = new BigInteger(pbitlength, 50,new SecureRandom());
if (e.gcd(p.subtract(ONE)).equals(ONE)) break;
}
for (;;)
{
//生成素數q,并且使q-1與e互素,與p不相等
for (;;)
{
q = new BigInteger(qbitlength,50,new SecureRandom());
if (e.gcd(q.subtract(ONE)).equals(ONE) && !p.equals(q)) break;
}
//模數n=p*q
n = p.multiply(q);
if (n.bitLength() == length) break;
p = p.max(q);
}
//pSub1=p-1
//qSub1=q-1
pSub1 = p.subtract(ONE);
qSub1 = q.subtract(ONE);
//計算(p-1)*(q-1)
phi = pSub1.multiply(qSub1);
//求私鑰指數d: 按公式d*e=n mod (p-1)(q-1)
d = e.modInverse(phi);
//應用中國剩余定理
//求CRT指數:dQ=d mod (q-1)
//求CRT指數:dP=d mod (p-1)
dP = d.remainder(pSub1);
dQ = d.remainder(qSub1);
//1/q mod p0
qInv = q.modInverse(p);
pukParam=new RSAPublicKey(n, e);
pvkParam=new RSAPrivateKey(n, e, d, p, q, dP, dQ, qInv);
return 1;
}
public byte[] encode(byte[] H, int outLen,int mHLen)
throws Exception
{
if (outLen < mTDefault.length + 10) {
throw new Exception("encoding too short");
}
byte[] T = new byte[mTDefault.length];
System.arraycopy(mTDefault,0,T,0,T.length);
System.arraycopy(H,0,T,T.length - mHLen,mHLen);
byte[] PS = new byte[outLen - T.length - 2];
for (int i = 0; i < PS.length; i++) {
PS[i] = (byte)0xFF;
}
// Create the output block, 01 || PS || 00 || T.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
baos.write((byte)0x01);
baos.write(PS);
baos.write((byte)0x00);
baos.write(T);
} catch (IOException ioe) {
// This should never happen
ioe.printStackTrace();
}
byte[] EM = baos.toByteArray();
return EM;
}
public byte[] decode(byte[] indata) throws Exception
{
if(indata.length<34)
throw new Exception("消息格式不對.");
if(indata[0]!=(byte)0x01)
{
throw new Exception("不是簽名的結果");
}
int start=0;
int outLen=indata.length;
while(indata[start]!=(byte)0x00)
{
start++;
if(start>=outLen)
throw new Exception("無效的填充數據!");
}
start++; // 跳過0
byte tm[]=new byte[outLen-start];
try {
System.arraycopy(indata,start,tm,0,tm.length);
}
catch (Exception ex) {
return null;
}
return tm;
}
public RSAPublicKey getPublicKey()
{
return pukParam;
}
public RSAPrivateKey getPrivateKey()
{
return pvkParam;
}
/**
* 將公鑰讀入
* @author 張榮華
*/
public RSAPublicKey readPuk(String strPukFileName)
throws IOException
{
FileInputStream fis = new FileInputStream(strPukFileName);
int fLength = fis.available();
byte[] bytePuk = new byte[fLength];
fis.read(bytePuk,0,fLength);
fis.close();
ByteArrayInputStream bIn = new ByteArrayInputStream(bytePuk);
DERInputStream dIn = new DERInputStream(bIn);
ASN1Sequence seq = (ASN1Sequence)dIn.readObject();
if(seq.size()==2)
{
DERInteger n = (DERInteger)seq.getObjectAt(0);
DERInteger e = (DERInteger)seq.getObjectAt(1);
return new RSAPublicKey(n.getValue(),e.getValue());
}
return null;
}
/**
* 將公鑰寫入到文件(DER)編碼
* @author 張榮華
*/
public int writePuk(RSAPublicKey puk,String strPukFileName)
throws IOException
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
DEROutputStream dOut = new DEROutputStream(bOut);
dOut.writeObject(puk.getDERObject());
byte[] m_bPuk=bOut.toByteArray();
dOut.close();
FileOutputStream fos = new FileOutputStream(strPukFileName);
fos.write(m_bPuk);
fos.flush();
fos.close();
return 1;
}
/**
* 將私鑰寫入到文件(DER編碼)
* @author 張榮華
*/
public int writePvk(RSAPrivateKey pvk,String strPvkFileName)
throws IOException
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
DEROutputStream dOut = new DEROutputStream(bOut);
dOut.writeObject(pvk.getDERObject());
byte[] m_bPvk=bOut.toByteArray();
dOut.close();
FileOutputStream fos = new FileOutputStream(strPvkFileName);
fos.write(m_bPvk);
fos.flush();
fos.close();
return 1;
}
/**
* 從文件讀入公鑰
* @author 張榮華
*/
public RSAPrivateKey readPvk(String strPvkFileName)
throws IOException
{
FileInputStream fis = new FileInputStream(strPvkFileName);
int fLength = fis.available();
byte[] bytePvk = new byte[fLength];
fis.read(bytePvk,0,fLength);
fis.close();
ByteArrayInputStream bIn = new ByteArrayInputStream(bytePvk);
DERInputStream dIn = new DERInputStream(bIn);
ASN1Sequence seq = (ASN1Sequence)dIn.readObject();
if(seq.size()==9)
{
DERInteger n = (DERInteger)seq.getObjectAt(1);
DERInteger e = (DERInteger)seq.getObjectAt(2);
DERInteger d = (DERInteger)seq.getObjectAt(3);
DERInteger p = (DERInteger)seq.getObjectAt(4);
DERInteger q = (DERInteger)seq.getObjectAt(5);
DERInteger dp = (DERInteger)seq.getObjectAt(6);
DERInteger dq = (DERInteger)seq.getObjectAt(7);
DERInteger qInv = (DERInteger)seq.getObjectAt(8);
return new RSAPrivateKey(
n.getValue(),e.getValue(),d.getValue(),
p.getValue(),q.getValue(),dp.getValue(),
dq.getValue(),qInv.getValue());
}
return null;
}
/**
* 以下是RSA算法的軟件實現測試程序
* @author 張榮華
*/
public static void main(String[] args) {
CRsa rsa= new CRsa();
// 密鑰生成測試
// 密鑰長度支持512 768 1024 2048 4096 再長也支持,但怕你的機器受不了
System.out.println("=====================密鑰生成測試======================");
rsa.generateKeyPair(512);
//rsa.savePukToFile("E:\\JavaProj\\temp\\puk.key");
//rsa.savePvkToFile("E:\\JavaProj\\temp\\pvk.key");
try {
rsa.writePuk(rsa.getPublicKey(),"E:\\JavaProj\\temp\\puk.key");
rsa.writePvk(rsa.getPrivateKey(),"E:\\JavaProj\\temp\\pvk.key");
// rsa.readPuk("E:\\JavaProj\\temp\\puk.key");
// rsa.readPvk("E:\\JavaProj\\temp\\pvk.key");
}
catch (IOException ex) {
}
System.out.println(rsa.getPublicKey().getModulus().toString(16));
// 公鑰加密私鑰解密測試
System.out.println("==================公鑰加密私鑰解密測試==================");
String str="你好,張榮華!";
byte[] indata=str.getBytes();
int indatalen=indata.length;
byte[] cipherData=null;
byte[] plainData=null;
try {
cipherData=rsa.PublicKeyEncrypt(indata,indatalen);
}
catch (Exception ex) {
//ex.printStackTrace();
}
try {
plainData=rsa.PrivateKeyDecrypt(cipherData,cipherData.length);
}
catch (Exception ex) {
//ex.printStackTrace();
}
System.out.println("解出的明文:\t"+new String(plainData));
System.out.println("長度(字節)=\t"+plainData.length);
// 數字簽名及簽名驗證測試
System.out.println("==================數字簽名及簽名驗證測試==================");
String strSign="這是一個簽名測試!";
byte[] signRes=null;
try {
// MD5WithRSA
signRes=rsa.signData(5,strSign.getBytes());
}
catch (Exception ex) {
ex.printStackTrace();
}
try {
int success=rsa.verifySignData(signRes,strSign.getBytes());
if(success==1)
System.out.println("簽名驗證成功!");
else
System.out.println("簽名驗證失敗!");
}
catch (Exception ex) {
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -