rsa使用简述 -凯发k8网页登录

 

rsa使用简述

rsa协议我不再描述,大家可以看。
rsa的密钥对生成时间依赖于两个因素,
第一,密钥的长度
第二,素数的筛选质量

在整个密钥对生成过程中,rsa会随机选择两个大素数,事实上,计算机的聪明
程度还不足以判断某个随机选择的大素数是否真的不可分解,因此,你只能够通过
计算机程序来尽量将这个大随机数不是素数的几率降到某个界限值(如0.0001)以下。

rsa keypair分为公钥和私钥,你应该这样使用keypair:
1,你使用私钥来签名,别人用你的公钥来验证签名
2,别人用你的公钥加密信息m->m',你用私钥来解密信息m'->m

虽然rsa经受过多年深入的密码分析,但大家在使用rsa的时候还是要注意以下事项,
否则rsa的安全性会大打折扣:

1,合理的密钥长度(setkeylength)
rsa1024至今是安全的,按照目前密码分析和计算机硬件条件的发展,估计在未来5-10年,
仍以难以破解。

2,素数确定性选择(setcertaintyofprime)
实际应用中,选择100就行了。

3,选择合理的padding(setrsamode)
rsa有三种模式,raw, pkcs和oaep,日常应用中,我本人只使用pkcs(pkcs#1 v1.5)
和oaep(pkcs#1 v2.0)这两种padding模式。
padding跟安全性其实是紧密挂钩的,有兴趣的朋友可以看看pkcs#1标准讨论。


我编写了一个rsautils的工具类,下面的该类的测试代码的一部分。

程序如下:
  rsautils utils =new rsautils();
  utils.setkeylength(1024);
  utils.setcertaintyofprime(100);
  utils.setrsamode(pkcs_rsa_mode);   //raw =1  pkcs=2  oaep=3
  utils.initrsakeypair();
  
  //查看公钥
  rsakeyparameters mypubkey=utils.getpublickey();
  biginteger mypubkey_modulus=mypubkey.getmodulus();  
  biginteger mypubkey_exponent=mypubkey.getexponent();
  system.out.println("##mypubkey的modulus长度=" mypubkey_modulus.bitlength());
  system.out.println("##mypubkey_modulus值=" mypubkey_modulus.tostring());
  system.out.println("##mypubkey的exponent长度=" mypubkey.getexponent().bitlength());
  system.out.println("##mypubkey_exponent值=" mypubkey_exponent.tostring());

  //查看私钥
  rsakeyparameters myprivkey=utils.getprivatekey();
  biginteger myprivkey_modulus=myprivkey.getmodulus();
  system.out.println("##myprivkey的modulus长度=" myprivkey_modulus.bitlength());
  system.out.println("##myprivkey的modulus值=" myprivkey_modulus.tostring());
  system.out.println("##myprivkey.getexponent()长度=" myprivkey.getexponent().bitlength());
  system.out.println("##myprivkey.getexponent()值=" myprivkey.getexponent());

以下是输出:
##mypubkey的modulus长度=1024
##mypubkey_modulus值=93806062666699782638132820491933031482836826566660997927543724649365705443512121003172409185855121369631538039111403612211728268332662414248776212969019881724066055080327735965218365399595323200109436472147258110417469825748181131149217613806780318374365617984326523029965066348377550281908277056378455106547
##mypubkey的exponent长度=2
##mypubkey_exponent值=3

##myprivkey的modulus长度=1024
##myprivkey的modulus值=93806062666699782638132820491933031482836826566660997927543724649365705443512121003172409185855121369631538039111403612211728268332662414248776212969019881724066055080327735965218365399595323200109436472147258110417469825748181131149217613806780318374365617984326523029965066348377550281908277056378455106547
##myprivkey.getexponent()长度=1023
##myprivkey.getexponent()值=62537375111133188425421880327955354321891217711107331951695816432910470295674747335448272790570080913087692026074269074807818845555108276165850808646013241363962278455328383552959397735977285649455021534046301135296075808377308404258909132811288204167107604525033796313576612747649866739561523887875979483707

其中,要记住,公钥的exponent即rsa算法中的e, e通常是3,17和65537
x.509建议使用65537,pem建议使用3,pkcs#1建议使用3或65537,一般来说,都是选择3。

私钥的exponent就是私钥中最重要的部分,它就是私钥区别于公钥的地方!

接着,我们看看rsa的加密,解密过程。

通常,不要随便对某一个别人发过来的东西进行签名(有潜在危险),即使有这样的必要,请先将它的文件进行digest或者hmac
处理后,再做签名。
为了说明rsa是如何加密信息的,我先让大家脱离md5/sha1等辅助算法(没有人会单独使用rsa,rsawithmd5,rsawithsha1才是常用的使用方法),来单独看看rsa本身:

大家习惯了des/idea,再看rsa的加密,可能会有一些不习惯,因为rsa虽然也可以看成是基于block的加密,但是,rsa的输入和输出的block的大小是不一样的,block的大小依赖于你所使用的rsa key的长度和rsa的padding模式。
在rsautils测试用例中,分别对rsa设置三种长度的key(768,1024,2048)和2种padding模式(pkcs 1.5和oaep),结果如下:

rsa                inblock大小   outblock大小  (单位,字节)
768bit/pkcs        85                96
1024bit/pkcs     117               128
2048bit/pkcs     245               256
768bit/oaep        54                96
1024bit/oaep     86               128
2048bit/oaep     214               256

大家可以看到,相同密钥长度, 加密出来的密文长度要比明文要长,且oaep的inblock/outblock要比pkcs的inblock/outblock要小,单从熵的角度,意味着oaep padding模式引入更多的熵,oaep要比pkcs更安全(事实上,为何提出oaep代替pkcs,大家可以到rsa网站看看oaep文档 )。


下面,rsautils是我写的针对bouncycastle的一个工具类,它封装了bouncycastle的crypto中的rsaengine,基本上,我很少单独使用rsautils,我更多的是结合diegestutils来使用。

posted on 2006-01-11 11:24 david.turing 阅读(10379) 评论(4)     所属分类: security领域

# re: rsa使用简述 2006-09-28 13:22

hello  回复     

# re: rsa使用简述 2007-11-02 18:33

大哥,能不能详细解释下pkcs#1 v1.5的签名算法padding过程,我现在做了sha1,得出结果为:adabc0dc670987ef47b557fb1554a32ddd5b545e,然后还要padding别的东西在前面吗?还是直接如下填充:
0001ffff......ffff00adabc0dc670987ef47b557fb1554a32ddd5b545e????
先谢谢大哥了!!!  回复     

# re: rsa使用简述 2007-11-02 18:37

我的邮箱:robie◎126.com  回复     

# re: rsa使用简述 2007-11-04 09:46 david.turing

如果你使用了sha1并对散列值进行rsa签名、加密,则padding的过程无需你本人去干预。
或者你可以看看下面的代码(rsautils.java):

package org.dev2dev.security.crypto.asymmetric;

import java.io.bufferedinputstream;
import java.io.bufferedoutputstream;
import java.io.bufferedreader;
import java.io.bytearrayinputstream;
import java.io.bytearrayoutputstream;
import java.io.fileinputstream;
import java.io.filenotfoundexception;
import java.io.fileoutputstream;
import java.io.ioexception;
import java.io.inputstream;
import java.io.inputstreamreader;
import java.io.outputstream;
import java.math.biginteger;
import java.security.securerandom;

import org.bouncycastle.crypto.asymmetricblockcipher;
import org.bouncycastle.crypto.asymmetriccipherkeypair;
import org.bouncycastle.crypto.datalengthexception;
import org.bouncycastle.crypto.encodings.oaepencoding;
import org.bouncycastle.crypto.encodings.pkcs1encoding;
import org.bouncycastle.crypto.engines.desengine;
import org.bouncycastle.crypto.engines.rsaengine;
import org.bouncycastle.crypto.generators.rsakeypairgenerator;
import org.bouncycastle.crypto.params.rsakeygenerationparameters;
import org.bouncycastle.crypto.params.rsakeyparameters;
import org.bouncycastle.crypto.params.rsaprivatecrtkeyparameters;
import org.bouncycastle.util.encoders.hex;
import org.dev2dev.security.crypto.blockcipher.blockciphertool;


/**
* rsa工具类
* @author david.turing
* @凯发天生赢家一触即发官网 copyright guangzhou bea usergroup
* @version 0.7
* @modifytime 22:30:34
*/
public class rsautils {

int keylength=1024;
int certainty=20;
rsakeygenerationparameters keyparam;
asymmetricblockcipher eng = null;
rsakeypairgenerator pgen = null;
asymmetriccipherkeypair pair = null;

public rsautils()
{

}

public string getname()
{
return "rsa";
}

/**
* 设置rsa的密钥长度
* @param rsakeylength
*/
public void setkeylength(int rsakeylength)
{
if(rsakeylength==512||rsakeylength==768||rsakeylength==1024||rsakeylength==2048)
keylength=rsakeylength;
}

/**
* 设置rsa key pair的素数产生经度,该数值越大,理论产生的rsa key安全性越高
* @param certaintyofprime
*/
public void setcertaintyofprime(int certaintyofprime)
{
certainty=certaintyofprime;
}

/**
* 生成rsa keypair,如果你不是通过importpublickey和importprivatekey
* 来导入密钥对,则可通过此方法随机生成。
*
* @return rsakeygenerationparameters
*/
public void initrsakeypair()
{
/**
* 注意, 第一个参数被写死了,它是publicexponent, 即e
* e通常选3,17,65537
* x.509建议使用65537
* pem建议使用3
* pkcs#1建议使用3或65537
* 在本算法中,它使用了3,即0x3
*/
rsakeygenerationparameters rsaparam=
new rsakeygenerationparameters(biginteger.valueof(0x3),
new securerandom(), this.keylength, this.certainty);
this.keyparam = rsaparam;
//rsa keypair的生成依赖于rsaparam
rsakeypairgenerator pgen = new rsakeypairgenerator();
pgen.init(keyparam);
pair = pgen.generatekeypair();
pair.getpublic();
}

/**
* 设置rsa密钥对,此方法用于从外部文件导入rsa密钥对
* @see importpublickey(string)
* @see importprivatekey(string)
* @param pubparam 公钥
* @param privparam 私钥
*/
public void setrsakeypair(rsakeyparameters pubparam, rsaprivatecrtkeyparameters privparam)
{
asymmetriccipherkeypair newpair=new asymmetriccipherkeypair(pubparam,privparam);
pair=newpair;

}

/**
* 该函数返回公钥
* @return
*/
public rsakeyparameters getpublickey()
{
return (rsakeyparameters)pair.getpublic();
}

/**
* 该函数返回私钥
* 注意,rsaprivatecrtkeyparameters其实继承了rsakeyparameters
* @see getpublickey()
* @return
*/
public rsaprivatecrtkeyparameters getprivatekey()
{
return (rsaprivatecrtkeyparameters)pair.getprivate();
}

/**
* rsa的padding模式,安全性依次递增
* mode=1 raw rsa 安全性最差
* mode=2 pkcs1
* mode=3 oaep
* @param mode
*/
public void setrsamode(int mode)
{
eng = new rsaengine(); //默认就是raw模式, 安全性问题,已不再使用
if (mode==2)
eng = new pkcs1encoding(eng);
else
eng = new oaepencoding(eng); //mode==3
}

/**
* 该rsaengine的每次处理输入数据,以block为单位,是32bytes
* 因此,本函数的输入要严格控制在32byte,即256bit数据
* 超出该长度会抛出异常。
* 本函数要求输入必须为16进制字符0-f。
*
* @see decrypt(string input)
* @param input
* @return
*/
public string encrypt(string input)
{

byte[] inputdata=hex.decode(input);

//用公钥加密
eng.init(true, pair.getpublic());

system.out.println(">>>加密参数");
system.out.println(">>>明文字节数:" inputdata.length);
system.out.println(">>>rsa engine input block size=" this.eng.getinputblocksize());
system.out.println(">>>rsa engine output block size=" this.eng.getoutputblocksize());

try
{
inputdata = eng.processblock(inputdata, 0, inputdata.length);
}
catch (exception e)
{
e.printstacktrace();
}

return new string(hex.encode(inputdata));
}

/**
* 该函数输入为字节,并规定其长度为32字节
* 超出该长度会抛出异常
* @see decrypt(byte[] inputdata)
* @param inputdata
* @return
*/
public byte[] encrypt(byte[] inputdata)
{
byte[] outputdata=null;

//用公钥加密
eng.init(true, pair.getpublic());

try
{
inputdata = eng.processblock(inputdata, 0, inputdata.length);
outputdata=new byte[eng.getoutputblocksize()];
outputdata=inputdata;
}
catch (exception e)
{
e.printstacktrace();
}

return outputdata;
}


/**
* 加密bytearrayinputstream流,在该方法中,会对input做分段处理,每段都将会
* 以inblocksize来划分明文,密文同样会设置换行,因此,将来在加密过程中,密文
* 需要分行读入,在明文、密文,唯一对应的是inblock和outblock,它们是换行对应的。
*
* 本函数已经处理结尾block问题
* @param input
* @param key
* @return
*/
public byte[] encryptpro(byte[] inputload)
{
bytearrayinputstream inputstream=new bytearrayinputstream(inputload);
bytearrayoutputstream outputstream=new bytearrayoutputstream();


//用公钥加密
eng.init(true, pair.getpublic());

int inblocksize =this.eng.getinputblocksize() ;
int outblocksize = this.eng.getoutputblocksize();

try {
system.out.println("加密的 inblocksize=" inblocksize);
system.out.println("加密的outblocksize=" outblocksize);

encryptpro(inputstream, outputstream);

} catch (datalengthexception e) {
e.printstacktrace();
} catch (illegalstateexception e) {
e.printstacktrace();
} catch(exception e){
e.printstacktrace();
}

byte[] outputload=outputstream.tobytearray();


system.out.println("###[1]明文大小:" inputload.length);
system.out.println("###[1]密文大小:" outputload.length);

return outputload;
}

/**
* 加密bufferedinputstream流,在该方法中,会对input做分段处理,每段都将会
* 以inblocksize来划分明文,密文同样会设置换行,因此,将来在加密过程中,密文
* 需要分行读入,在明文、密文,唯一对应的是inblock和outblock,它们是换行对应的。
*
*此函数未处理padding,如果你不想自己调整padding,请用encryptpro
*@see encryptpro(bufferedinputstream inputstream,bufferedoutputstream outputstream)
*
* @param input
* @param key
* @return
*/
public void encrypt(bufferedinputstream inputstream,bufferedoutputstream outputstream)
{
//用公钥加密
eng.init(true, pair.getpublic());

int inblocksize =this.eng.getinputblocksize() ;
int outblocksize = this.eng.getoutputblocksize();

byte[] inblock = new byte[inblocksize];
byte[] outblock = new byte[outblocksize];

byte[] rv = null;
try {
while (inputstream.read(inblock, 0, inblocksize) > 0)
{
outblock = eng.processblock(inblock, 0, inblocksize);
rv = hex.encode(outblock, 0, outblocksize);
outputstream.write(rv, 0, rv.length);
outputstream.write('\n');

}

} catch (datalengthexception e) {
e.printstacktrace();
} catch (illegalstateexception e) {
e.printstacktrace();
} catch(exception e){
e.printstacktrace();
}

}


/**
* 加密bufferedinputstream流,在该方法中,会对input做分段处理,每段都将会
* 以inblocksize来划分明文,密文同样会设置换行,因此,将来在加密过程中,密文
* 需要分行读入,在明文、密文,唯一对应的是inblock和outblock,它们是换行对应的。
*
* 该函数会在加密文件的头部注明padding_size
* padding_size即padding_size即明文流按照inblocksize划分后
* 最后一个block的未占满的大小(字节数)
*
* @param input
* @param key
* @return
*/
public void encryptpro(inputstream inputstream,outputstream outputstream)
{
//用公钥加密
eng.init(true, pair.getpublic());

int inblocksize =this.eng.getinputblocksize() ;
int outblocksize = this.eng.getoutputblocksize();

byte[] inblock = new byte[inblocksize];
byte[] outblock = new byte[outblocksize];


byte[] rv = null;

try {

//system.out.println("stream length=" inputstream.available());
int padding_size=inblocksize-(inputstream.available() % inblocksize);
//system.out.println("padding_size=" padding_size);

/*写入padding_size,处理最后一个block不够inblocksize的情况
* 记住不要自己修改inblocksize,因为rsa共有三种模式,每种模式
* 对padding的处理方式都不一样,所以,不要修改对processblock
* 的加密解密方式。总之,不要修改rsa的inblock!
*/
outputstream.write((padding_size "").getbytes());
outputstream.write('\n');

while (inputstream.read(inblock, 0, inblocksize) > 0)
{
outblock = eng.processblock(inblock, 0, inblocksize);
rv = hex.encode(outblock, 0, outblocksize);

//system.out.println("hex len=" rv.length);
outputstream.write(rv, 0, rv.length);

outputstream.write('\n');
}

} catch (datalengthexception e) {
e.printstacktrace();
} catch (illegalstateexception e) {
e.printstacktrace();
} catch(exception e){
e.printstacktrace();
}

}

/**
* 解密字符串
* @param input
* @return
*/
public string decrypt(string input)
{

byte[] inputdata=hex.decode(input);

eng.init(false,pair.getprivate());
system.out.println(">>>加密参数");
system.out.println(">>>rsa engine input block size=" this.eng.getinputblocksize());
system.out.println(">>>rsa engine output block size=" this.eng.getoutputblocksize());

try
{
inputdata=eng.processblock(inputdata,0,inputdata.length);
}
catch(exception e)
{
e.printstacktrace();
}

return new string(hex.encode(inputdata));

}

/**
* 解密字节数组
* @param inputdata
* @return
*/
public byte[] decrypt(byte[] inputdata)
{
byte[] outputdata=null;

//用公钥加密
eng.init(false, pair.getprivate());

try
{
inputdata = eng.processblock(inputdata, 0, inputdata.length);
outputdata=new byte[eng.getoutputblocksize()];
outputdata=inputdata;
}
catch (exception e)
{
e.printstacktrace();
}

return outputdata;
}

/**
* 解密流
*
* 本函数已经处理结尾block问题
* @see encryptpro(byte[] inputload)
*
* @param inputstream 被加密过的流
* @param outputstream 解密输出的流
*/
public byte[] decryptpro(byte[] inputload)
{

bytearrayinputstream inputstream=new bytearrayinputstream(inputload);
bytearrayoutputstream outputstream=new bytearrayoutputstream();

//设置引擎
eng.init(false, pair.getprivate());

int inblocksize =this.eng.getinputblocksize() ;
int outblocksize = this.eng.getoutputblocksize();

try {
system.out.println("解密的in blocksize=" inblocksize);
system.out.println("解密的out blocksize=" outblocksize);

this.decryptpro(inputstream, outputstream);
} catch (datalengthexception e) {
e.printstacktrace();
} catch (illegalstateexception e) {
e.printstacktrace();
}
catch(exception e)
{
e.printstacktrace();
}

//system.out.println("解密。。。outputload=" new string(outputload));

//byte[] outputload=new byte[outputstream.size()];
byte[] outputload=outputstream.tobytearray();

system.out.println("###[2]密文大小:" inputload.length);
system.out.println("###[2]明文大小:" outputload.length);

return outputload;
}



/**
* 解密rsa流,首先先读取rsa的流的padding_size(第一行)
*
* @param inputstream 被加密过的流
* @param outputstream 解密输出的流
*/
public void decryptpro(inputstream inputstream, outputstream outputstream)
{
//设置引擎
eng.init(false, pair.getprivate());

bufferedreader br = new bufferedreader(new inputstreamreader(inputstream));

int inblocksize =this.eng.getinputblocksize() ;
int outblocksize = this.eng.getoutputblocksize();

int lines;

byte[] outblock = new byte[outblocksize];

string rv = null;
int inl=0;
byte[] last=null;

try {
int amout=inputstream.available();
lines=amout/(inblocksize*2);
//system.out.println("lines=" lines);
rv=br.readline();

//system.out.println("#########padding size=" rv);
int padding_size=integer.parseint(rv);

while ((rv = br.readline()) != null)
{
lines--;
/* 要注意,hex处理密文是将每个byte用2个16进制表示
* 一个hex码其实只需4bit来表示,一个byte有8bit,因此
* 需要2个hex码表示,所以,一个字符经hex encode会
* 变成两个hex字符。
*/
inl=rv.length()/2;
last=new byte[inl];
last = hex.decode(rv);

outblock = eng.processblock(last, 0, inblocksize);

if(lines>0)
{
outputstream.write(outblock, 0, outblocksize);
}
else
outputstream.write(outblock, 0, outblocksize-padding_size);

}

} catch (datalengthexception e) {
e.printstacktrace();
} catch (illegalstateexception e) {
e.printstacktrace();
}
catch(exception e)
{
e.printstacktrace();
}

}

/**
* 输出公钥到文件
* @param filename
*/
public void exportpublickey(string filename)
{
string outfile = filename;
bufferedoutputstream outstream = null;

try
{
outstream = new bufferedoutputstream(new fileoutputstream(outfile));
}
catch (ioexception fnf)
{
system.err.println("无法创建公钥文件 [" outfile "]");
system.exit(1);
}


rsakeyparameters mypubkey=this.getpublickey();
biginteger mypubkey_modulus=mypubkey.getmodulus();
biginteger mypubkey_exponent=mypubkey.getexponent();
system.out.println("[exportpublickey]mypubkey_modulus=" mypubkey_modulus.tostring());
system.out.println("[exportpublickey]mypubkey_exponent=" mypubkey_exponent);

try
{
outstream.write(mypubkey_modulus.tostring().getbytes());
outstream.write('\n');
outstream.write(mypubkey_exponent.tostring().getbytes());
outstream.flush();
outstream.close();
}
catch (ioexception closing)
{
closing.printstacktrace();
}
system.out.println("公钥输出到文件:" filename);

}

/**
* 从文件中导入公钥到内存
* @param filename
* @return
*/
public rsakeyparameters importpublickey(string filename)
{
string infile = filename;
bufferedinputstream instream = null;
rsakeyparameters rsaparam=null;
try
{
instream = new bufferedinputstream(new fileinputstream(infile));
}
catch (filenotfoundexception fnf)
{
system.err.println("公钥文件没有找到 [" infile "]");
system.exit(1);
}

bufferedreader br = new bufferedreader(new inputstreamreader(instream));
biginteger mypubkey_modulus=null;
biginteger mypubkey_exponent=null;
string readstr=null;

try {

readstr = br.readline();

mypubkey_modulus= new biginteger(readstr);
system.out.println("[importpublickey]mypubkey_modulus=" mypubkey_modulus.tostring());

readstr = br.readline();
mypubkey_exponent=new biginteger(readstr);
system.out.println("[importpublickey]mypubkey_exponent=" mypubkey_exponent);

rsaparam=new rsakeyparameters(false,mypubkey_modulus,mypubkey_exponent);

} catch (datalengthexception e) {
e.printstacktrace();
} catch (illegalstateexception e) {
e.printstacktrace();
}
catch(exception e)
{
e.printstacktrace();
}
return rsaparam;

}

/**
* 输出私钥到指定的文件
* @param filename
*/
public void exportprivatekey(string filename)
{

string outfile = filename;
bufferedoutputstream outstream = null;

try
{
outstream = new bufferedoutputstream(new fileoutputstream(outfile));
}
catch (ioexception fnf)
{
system.err.println("输出文件无法创建 [" outfile "]");
system.exit(1);
}


rsaprivatecrtkeyparameters myprivkey=this.getprivatekey();

biginteger myprivkey_modulus=myprivkey.getmodulus();
biginteger myprivkey_exponent=myprivkey.getexponent();
biginteger e=myprivkey.getpublicexponent(); //e is public
biginteger dp=myprivkey.getdp();
biginteger dq=myprivkey.getdq();
biginteger p=myprivkey.getp();
biginteger q=myprivkey.getq();
biginteger qinv=myprivkey.getqinv();


try
{
outstream.write(myprivkey_modulus.tostring().getbytes());
outstream.write('\n');
outstream.write(e.tostring().getbytes());
outstream.write('\n');
outstream.write(myprivkey_exponent.tostring().getbytes());
outstream.write('\n');
outstream.write(p.tostring().getbytes());
outstream.write('\n');
outstream.write(q.tostring().getbytes());
outstream.write('\n');
outstream.write(dp.tostring().getbytes());
outstream.write('\n');
outstream.write(dq.tostring().getbytes());
outstream.write('\n');
outstream.write(qinv.tostring().getbytes());
outstream.write('\n');

outstream.flush();
outstream.close();
}
catch (ioexception closing)
{
closing.printstacktrace();
}
system.out.println("私钥输出到文件:" filename);

}

/**
* 输出私钥到指定的文件,私钥经过密码加密
* 强烈建议在生产环境中使用此方法而不要使用
* exportprivatekey(string filename)
*
* @param filename 私钥文件
* @param password 私钥的保护密码
*/
public void exportprivatekeywithpass(string filename, string password)
{

string outfile = filename;

bytearrayoutputstream outstream=null;
bufferedoutputstream keyoutstream=null;
//借助blockciphertool来加密私钥
blockciphertool ciphertool=new blockciphertool();

//暂时使用des加密私钥
//ciphertool.setengine(new aesengine());
//ciphertool.setengine(new ideaengine());
ciphertool.setengine(new desengine());
//ciphertool.setengine(new blowfishengine());

//ciphertool.setkeylength(64); //aes 32(hex)*4=128bit
//string keystr="123456789012345678901234567890ff"; //16进制 128bit aes key
//string keystr="123456789012345678901234567890ff123456789012345678901234567890ff"; //16进制 256bit aes key
//string keystr="123456789012345678901234567890ff"; //16进制 128bit idea key
//string keystr="0123456789abcdef"; //16进制 64bit(56) des key
//string keystr="0123456789abcdef"; //16进制 64bit(56) blowfish key


outstream = new bytearrayoutputstream();
try
{
keyoutstream = new bufferedoutputstream(new fileoutputstream(outfile));

}
catch (exception fnf)
{
system.err.println("输出文件无法创建 [" outfile "]");
system.exit(1);
}


rsaprivatecrtkeyparameters myprivkey=this.getprivatekey();

biginteger myprivkey_modulus=myprivkey.getmodulus();
biginteger myprivkey_exponent=myprivkey.getexponent();
biginteger e=myprivkey.getpublicexponent(); //e is public
biginteger dp=myprivkey.getdp();
biginteger dq=myprivkey.getdq();
biginteger p=myprivkey.getp();
biginteger q=myprivkey.getq();
biginteger qinv=myprivkey.getqinv();


try
{
// 产生正确的私钥流
outstream.write(myprivkey_modulus.tostring().getbytes());
outstream.write('\n');
outstream.write(e.tostring().getbytes());
outstream.write('\n');
outstream.write(myprivkey_exponent.tostring().getbytes());
outstream.write('\n');
outstream.write(p.tostring().getbytes());
outstream.write('\n');
outstream.write(q.tostring().getbytes());
outstream.write('\n');
outstream.write(dp.tostring().getbytes());
outstream.write('\n');
outstream.write(dq.tostring().getbytes());
outstream.write('\n');
outstream.write(qinv.tostring().getbytes());
outstream.write('\n');


byte[] privatekey_withtoutpass=outstream.tobytearray();

bytearrayinputstream keyinstream=new bytearrayinputstream(privatekey_withtoutpass);

//加密私钥
ciphertool.init(true,password);
//将outstream转型成keyinstream,将keyinstream执行des加密
ciphertool.encrypt(keyinstream,keyoutstream);

keyinstream.close();
keyoutstream.flush();
keyoutstream.close();


}
catch (ioexception closing)
{
closing.printstacktrace();
}

system.out.println("私钥经过加密并输出到文件:" filename);

}

/**
* 从某个文件中导入私钥,假定私钥未被加密
* @see exportprivatekey(string filename)
* @param filename
* @return
*/
public rsaprivatecrtkeyparameters importprivatekey(string filename)
{
string infile = filename;
bufferedinputstream instream = null;
rsaprivatecrtkeyparameters rsaprivparam=null;

try
{
instream = new bufferedinputstream(new fileinputstream(infile));
}
catch (filenotfoundexception fnf)
{
system.err.println("私钥文件没有找到 [" infile "]");
system.exit(1);
}

bufferedreader br = new bufferedreader(new inputstreamreader(instream));


biginteger myprivkey_modulus=null;
biginteger myprivkey_exponent=null;
biginteger e=null;
biginteger p=null;
biginteger q=null;
biginteger dp=null;
biginteger dq=null;
biginteger qinv=null;

string readstr=null;
try {

readstr = br.readline();
myprivkey_modulus= new biginteger(readstr);
readstr = br.readline();
e= new biginteger(readstr);
readstr = br.readline();
myprivkey_exponent= new biginteger(readstr);
readstr = br.readline();
p= new biginteger(readstr);
readstr = br.readline();
q= new biginteger(readstr);
readstr = br.readline();
dp= new biginteger(readstr);
readstr = br.readline();
dq= new biginteger(readstr);
readstr = br.readline();
qinv= new biginteger(readstr);


rsaprivparam=new rsaprivatecrtkeyparameters(myprivkey_modulus, myprivkey_exponent,
e,p,q,dp,dq,qinv);

} catch (datalengthexception ex) {
ex.printstacktrace();
} catch (illegalstateexception ex) {
ex.printstacktrace();
}
catch(exception ex)
{
ex.printstacktrace();
}
return rsaprivparam;

}

/**
* 从私钥文件中导入私钥,并用保护密码通过des解密该私钥
* 放入内存,该方法跟exportprivatekeywithpass 对应
*
* @see exportprivatekeywithpass(string filename, string password)
* @param filename
* @param password
* @return
*/
public rsaprivatecrtkeyparameters importprivatekeywithpass(string filename,string password)
{
string infile = filename;
inputstream instream = null;

bytearrayinputstream keyinstream =null;
bytearrayoutputstream keyoutstream = new bytearrayoutputstream();

//借助blockciphertool来加密私钥
blockciphertool ciphertool=new blockciphertool();

//暂时使用des加密私钥
//ciphertool.setengine(new aesengine());
//ciphertool.setengine(new ideaengine());
ciphertool.setengine(new desengine());
//ciphertool.setengine(new blowfishengine());

//ciphertool.setkeylength(64); //aes 32(hex)*4=128bit
//string keystr="123456789012345678901234567890ff"; //16进制 128bit aes key
//string keystr="123456789012345678901234567890ff123456789012345678901234567890ff"; //16进制 256bit aes key
//string keystr="123456789012345678901234567890ff"; //16进制 128bit idea key
//string keystr="0123456789abcdef"; //16进制 64bit(56) des key
//string keystr="0123456789abcdef"; //16进制 64bit(56) blowfish key


rsaprivatecrtkeyparameters rsaprivparam=null;
try
{
instream = new bufferedinputstream(new fileinputstream(infile));
}
catch (filenotfoundexception fnf)
{
system.err.println("私钥文件没有找到 [" infile "]");
system.exit(1);
}

ciphertool.init(false,password);

//keyinstream-->bytearrayoutputstream,将keyinstream执行des加密
ciphertool.decrypt(instream,keyoutstream);

byte[] privatekey_withtoutpass=keyoutstream.tobytearray();

keyinstream=new bytearrayinputstream(privatekey_withtoutpass);



biginteger myprivkey_modulus=null;
biginteger myprivkey_exponent=null;
biginteger e=null;
biginteger p=null;
biginteger q=null;
biginteger dp=null;
biginteger dq=null;
biginteger qinv=null;

string readstr=null;
try {

bufferedreader br = new bufferedreader(new inputstreamreader(keyinstream));

readstr = br.readline();
myprivkey_modulus= new biginteger(readstr);
readstr = br.readline();
e= new biginteger(readstr);
readstr = br.readline();
myprivkey_exponent= new biginteger(readstr);
readstr = br.readline();
p= new biginteger(readstr);
readstr = br.readline();
q= new biginteger(readstr);
readstr = br.readline();
dp= new biginteger(readstr);
readstr = br.readline();
dq= new biginteger(readstr);
readstr = br.readline();
qinv= new biginteger(readstr);


rsaprivparam=new rsaprivatecrtkeyparameters(myprivkey_modulus, myprivkey_exponent,
e,p,q,dp,dq,qinv);


keyinstream.close();
keyoutstream.flush();
keyoutstream.close();

} catch (datalengthexception ex) {
ex.printstacktrace();
} catch (illegalstateexception ex) {
ex.printstacktrace();
}
catch(exception ex)
{
ex.printstacktrace();
}

return rsaprivparam;

}

/**
* 为一个block清0
* @param block
*/
public void reset(byte[] block)
{
for(int i=0;i block[i]=(byte)0;
}

/**
* 将某个block自off后的字节清0
* @param block
* @param off
*/
public void padding(byte[] block, int off)
{
for(int i=off;i block[i]=(byte)0;
}


}
  回复     

导航

统计

常用链接

留言簿(109)

我参与的团队

随笔分类(126)

随笔档案(155)

文章分类(9)

文章档案(19)

相册

搜索

积分与排名

最新随笔

最新评论

阅读排行榜

评论排行榜

网站地图