📄 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 + -