📄 crsa.java
字号:
package org.infosecurity.cryptography;
/**
* <p>Title: RSA算法的软件实现 </p>
* <p>Description: RSA算法的软件实现,功能包括:公钥加密私钥解密</p>
* <p>数字签名和签名验证,密钥对(公私钥)的生成,遵循PKCS标准</p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: 中信信息安全组织(CISO)</p>
* @author 张荣华
* @version 1.0.2003.0704
*/
import java.io.*;
import java.math.*;
import java.util.*;
import java.security.SecureRandom;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.x509.*;
import org.bouncycastle.util.encoders.*;
public class CRsa extends Object implements Serializable {
// HASH算法的缺省摘要的信息
private final static byte[] SHA1_DIGEST_INFO = {
(byte)0x30, (byte)0x21, (byte)0x30, (byte)0x09, (byte)0x06,
(byte)0x05, (byte)0x2b, (byte)0x0e, (byte)0x03, (byte)0x02,
(byte)0x1a, (byte)0x05, (byte)0x00, (byte)0x04, (byte)0x14,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
};
private final static byte[] MD5_DIGEST_INFO = {
(byte)0x30, (byte)0x20, (byte)0x30, (byte)0x0c, (byte)0x06,
(byte)0x08, (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86,
(byte)0xf7, (byte)0x0d, (byte)0x02, (byte)0x05, (byte)0x05,
(byte)0x00, (byte)0x04, (byte)0x10, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
};
private byte[] mTDefault=null;
private int mLen=0;
//
private SecureRandom secureRd=new SecureRandom();
private static BigInteger ONE = BigInteger.valueOf(1);
private static BigInteger TWO = BigInteger.valueOf(2);
// ebase为17
private static BigInteger eBase = BigInteger.valueOf(0x11);
RSAPublicKey pukParam=null;
RSAPrivateKey pvkParam=null;
public CRsa() {
}
/**
* 设置公钥
*/
public void setPublicKey(RSAPublicKey puk)
{
this.pukParam = puk;
}
/**
* 设置私钥
*/
public void setPrivateKey(RSAPrivateKey pvk)
{
this.pvkParam = pvk;
this.pukParam = new RSAPublicKey(pvk.getModulus(),pvk.getExponent());
}
/**
* 公钥加密
*/
public byte[] PublicKeyEncrypt(byte[] indata,int indatalen)
throws DataLengthException
{
int k=getInputBlockSize(true);
byte EncryptBlock[]=null;
// PS依据输入数据的长度>8
if (indatalen > getInputBlockSize(true)-10)
{
throw new DataLengthException("输入RSA加密的数据太长.\n");
}
ByteArrayOutputStream baos=new ByteArrayOutputStream();
byte[] PS=new byte[(getOutputBlockSize(true)-indatalen-2)];
for(int i=0;i<PS.length;i++)
{
PS[i]=(byte)(secureRd.nextInt(255)+1);
}
try
{
baos.write((byte)0x02);
baos.write(PS);
baos.write((byte)0x00);
baos.write(indata);
}catch(IOException ioe){
ioe.printStackTrace();
}
EncryptBlock=baos.toByteArray();
BigInteger input = new BigInteger(1, EncryptBlock);
byte[] output=null;
output = input.modPow(pukParam.getExponent(), pukParam.getModulus()).toByteArray();
if (output[0] == 0 && output.length > getOutputBlockSize(true))//比输出长度长,截断
{
byte[] tmp = new byte[output.length - 1];
System.arraycopy(output, 1, tmp, 0, tmp.length);
return tmp;
}
if (output.length < getOutputBlockSize(true)) // 比输出长度短,增长
{
byte[] tmp = new byte[getOutputBlockSize(true)];
System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length);
return tmp;
}
return output;
}
/**
* 私钥解密
*/
public byte[] PrivateKeyDecrypt(byte[] indata,int indatalen)
throws DataLengthException
{
int padLength=0;
if (indatalen > getInputBlockSize(false))
{
throw new DataLengthException("输入RSA解密的数据太长.");
}
byte[] output=null;
BigInteger input=new BigInteger(1,indata);
output = input.modPow(pvkParam.getPrivateExponent(), pukParam.getModulus()).toByteArray();
if(output.length<10)
throw new DataLengthException("消息格式不对.");
if(output[0]!=(byte)0x02)
{
throw new DataLengthException("不是公钥操作的结果");
}
int start=0;
int outLen=output.length;
while(output[start]!=(byte)0x00)
{
start++;
if(start>=outLen)
throw new DataLengthException("无效的填充数据!");
}
start++; // 跳过0
byte tm[]=new byte[outLen-start];
try {
System.arraycopy(output,start,tm,0,tm.length);
}
catch (Exception ex) {
return null;
}
return tm;
}
/**
* 数字签名
* @param HashAlgorith 散列算法(5--md5 3--sha1)
* @param indata 输入数据
*/
public byte[] signData(int HashAlgorithm,byte[] indata)
throws Exception
{
int indatalen=indata.length;
byte[] hashRes=null;
int blockLen=getInputBlockSize(true);
if(HashAlgorithm==5)
hashRes=new byte[16];
else if(HashAlgorithm==3)
hashRes=new byte[20];
else
throw new Exception("不支持的散列算法!");
if(indata==null||indata.length==0)
throw new Exception("输入数据为空");
if(HashAlgorithm==5)
{
// 生成摘要
mTDefault=new byte[MD5_DIGEST_INFO.length];
mLen=16;
System.arraycopy(MD5_DIGEST_INFO,0,mTDefault,0,mTDefault.length);
CMd5 md5=new CMd5();
for(int i=0;i<indatalen;i++)
md5.update(indata[i]);
md5.doFinal(hashRes,0);
// 摘要编码
// 待编码的长度要比密钥的长度小1
byte inbyte[]=encode(hashRes,getOutputBlockSize(true)-1,16);
// 签名
byte[] signData=null;
BigInteger input=new BigInteger(1,inbyte);
signData = input.modPow(pvkParam.getPrivateExponent(), pukParam.getModulus()).toByteArray();
// 如果是正数转成一个字节数组,我们将得到一个以0开头的结果
if (signData[0] == 0 && signData.length > getOutputBlockSize(true))//比输出长度长,截断
{
byte[] tmp = new byte[signData.length - 1];
System.arraycopy(signData, 1, tmp, 0, tmp.length);
return tmp;
}
if (signData.length < getOutputBlockSize(true)) // 比输出长度短,增长
{
byte[] tmp = new byte[getOutputBlockSize(true)];
System.arraycopy(signData, 0, tmp, tmp.length - signData.length, signData.length);
return tmp;
}
return signData;
}
if(HashAlgorithm==3)
{
mTDefault=new byte[SHA1_DIGEST_INFO.length];
mLen=20;
System.arraycopy(SHA1_DIGEST_INFO,0,mTDefault,0,mTDefault.length);
CSha1 sha1=new CSha1();
for(int i=0;i<indatalen;i++)
sha1.update(indata[i]);
sha1.doFinal(hashRes,0);
// 摘要编码
byte inbyte[]=encode(hashRes,getOutputBlockSize(true)-1,20);
// 签名
byte[] signData=null;
BigInteger input=new BigInteger(1,inbyte);
signData = input.modPow(pvkParam.getPrivateExponent(), pukParam.getModulus()).toByteArray();
if (signData[0] == 0 && signData.length > getOutputBlockSize(true))//比输出长度长,截断
{
byte[] tmp = new byte[signData.length - 1];
System.arraycopy(signData, 1, tmp, 0, tmp.length);
return tmp;
}
if (signData.length < getOutputBlockSize(true)) // 比输出长度短,增长
{
byte[] tmp = new byte[getOutputBlockSize(true)];
System.arraycopy(signData, 0, tmp, tmp.length - signData.length, signData.length);
return tmp;
}
return signData;
}
return null;
}
/**
* 验证数字签名
*/
public int verifySignData(byte[] indata,byte[] plainData)throws Exception
{
try {
if(indata.length>getInputBlockSize(false))
throw new Exception("签名的输入长度过长!");
BigInteger input=new BigInteger(1,indata);
byte[] out = input.modPow(pukParam.getExponent(), pukParam.getModulus()).toByteArray();
byte[] bEncodedHash=decode(out);
ByteArrayInputStream bIn=null;
bIn = new ByteArrayInputStream(bEncodedHash);
DERInputStream dIn = new DERInputStream(bIn);
ASN1Sequence seq = (ASN1Sequence)dIn.readObject();
if(seq.size()==2)
{
DigestInfo digestInf=DigestInfo.getInstance(seq);
AlgorithmIdentifier aID=digestInf.getAlgorithmId();
if(aID.getObjectId().getId().equals("1.2.840.113549.2.5"))//MD5
{
// 生成摘要
int plainDataLength=0;
plainDataLength=plainData.length;
byte[] plainHash=new byte[16];
CMd5 md5=new CMd5();
for(int i=0;i<plainDataLength;i++)
md5.update(plainData[i]);
md5.doFinal(plainHash,0);
byte[] digest=digestInf.getDigest();
for(int i=0;i<md5.getDigestSize();i++)
{
//System.out.println("result="+digest[i]+"plain="+plainHash[i]);
if(digest[i]==plainHash[i])
{
//调试输出语句
continue;
}
else
return 0;
}
return 1;
}
else if(aID.getObjectId().getId().equals("1.3.14.3.2.26"))
{
// 生成摘要
int plainDataLength=0;
plainDataLength=plainData.length;
byte[] plainHash=new byte[20];
CSha1 sha1=new CSha1();
for(int i=0;i<plainDataLength;i++)
sha1.update(plainData[i]);
sha1.doFinal(plainHash,0);
byte[] digest=digestInf.getDigest();
for(int i=0;i<sha1.getDigestSize();i++)
{
if(digest[i]==plainHash[i])
continue;
else
return 0;
}
return 1;
}
else
{
// 目前不支持该算法
return 0;
}
}
else
return 0;
}
catch (Exception e) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -