【下载实例】本文介绍RSA2加密与解密,RSA2是RSA的加强版本,在密钥长度上采用2048, RSA2比RSA更安全,更可靠, 本人的另一篇文章RSA已经发表,有想了解的可以点开下面的RSA文章
‘贰’ 怎样用Java实现RSA加密
提供加密,解密,生成密钥对等方法。�梢愿�模��遣灰��螅�裨蛐�驶岬� keyPairGen.initialize(KEY_SIZE, new SecureRandom()); KeyPair keyPair = keyPairGen.genKeyPair(); return keyPair; } catch (Exception e) { throw new Exception(e.getMessage()); } } /** * 生成公钥 * @param molus * @param publicExponent * @return RSAPublicKey * @throws Exception */ public static RSAPublicKey generateRSAPublicKey(byte[] molus, byte[] publicExponent) throws Exception { KeyFactory keyFac = null; try { keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider()); } catch (NoSuchAlgorithmException ex) { throw new Exception(ex.getMessage()); } RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(molus), new BigInteger(publicExponent)); try { return (RSAPublicKey) keyFac.generatePublic(pubKeySpec); } catch (InvalidKeySpecException ex) { throw new Exception(ex.getMessage()); } } /** * 生成私钥 * @param molus * @param privateExponent * @return RSAPrivateKey * @throws Exception */ public static RSAPrivateKey generateRSAPrivateKey(byte[] molus, byte[] privateExponent) throws Exception { KeyFactory keyFac = null; try { keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider()); } catch (NoSuchAlgorithmException ex) { throw new Exception(ex.getMessage()); } RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(molus), new BigInteger(privateExponent)); try { return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec); } catch (InvalidKeySpecException ex) { throw new Exception(ex.getMessage()); } } /** * 加密 * @param key 加密的密钥 * @param data 待加密的明文数据 * @return 加密后的数据 * @throws Exception */ public static byte[] encrypt(Key key, byte[] data) throws Exception { try { Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider()); cipher.init(Cipher.ENCRYPT_MODE, key); int blockSize = cipher.getBlockSize();//获得加密块大小� i++; } return raw; } catch (Exception e) { throw new Exception(e.getMessage()); } } /** * 解密 * @param key 解密的密钥 * @param raw 已经加密的数据 * @return 解密后的明文 * @throws Exception */ public static byte[] decrypt(Key key, byte[] raw) throws Exception { try { Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider()); cipher.init(cipher.DECRYPT_MODE, key); int blockSize = cipher.getBlockSize(); ByteArrayOutputStream bout = new ByteArrayOutputStream(64); int j = 0; while (raw.length - j * blockSize > 0) { bout.write(cipher.doFinal(raw, j * blockSize, blockSize)); j++; } return bout.toByteArray(); } catch (Exception e) { throw new Exception(e.getMessage()); } } /** * * @param args * @throws Exception */ public static void main(String[] args) throws Exception { File file = new File("c:/test.html"); FileInputStream in = new FileInputStream(file); ByteArrayOutputStream bout = new ByteArrayOutputStream(); byte[] tmpbuf = new byte[1024]; int count = 0; while ((count = in.read(tmpbuf)) != -1) { bout.write(tmpbuf, 0, count); tmpbuf = new byte[1024]; } in.close(); byte[] orgData = bout.toByteArray(); KeyPair keyPair = RSA.generateKeyPair(); RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate(); byte[] pubModBytes = pubKey.getMolus().toByteArray(); byte[] pubPubExpBytes = pubKey.getPublicExponent().toByteArray(); byte[] priModBytes = priKey.getMolus().toByteArray(); byte[] priPriExpBytes = priKey.getPrivateExponent().toByteArray(); RSAPublicKey recoveryPubKey = RSA.generateRSAPublicKey(pubModBytes,pubPubExpBytes); RSAPrivateKey recoveryPriKey = RSA.generateRSAPrivateKey(priModBytes,priPriExpBytes); byte[] raw = RSA.encrypt(priKey, orgData); file = new File("c:/encrypt_result.dat"); OutputStream out = new FileOutputStream(file); out.write(raw); out.close(); byte[] data = RSA.decrypt(recoveryPubKey, raw); file = new File("c:/decrypt_result.html"); out = new FileOutputStream(file); out.write(data); out.flush(); out.close(); } } (责任编辑:云子)
‘叁’ c#怎么调用java生成的RSA 公钥进行加密
NET无法调用JAVA产生的RSA公钥,必须将RSA算法在.NET里面重写才行,在.NET里面RSA的公钥长度是128位的,但是你给出的JAVA公钥却是159位长度,非常的不标准,公钥长度不满足128的肯定无法给.NET使用。
这里最多帮做个对应解析,数据是肯定无法用的:
将java的RSA公钥最后四个字母AQAB分割开,用.NET的xml格式表示就是
<RSAKeyValue><Molus>
/qp
jLFfDCu3qytxf+/IoCYE
+Hf4hsEDUKV2kkhRJsnwwID</Molus><Exponent>AQAB</Exponent>
</RSAKeyValue>
这里的数据都是用的BASE64编码,你用BASE64解码后可以得到byte[],就可以看到密钥长度了,实际密钥要转换为BigInteger后才能参与RSA核心运算
‘肆’ JAVA里面RSA加密算法的使用
RSA的Java实现不能一次加密很大的字符,自己处理了一下,见下面的代码。Base64编码类用的是一个Public domain Base64 for java http://iharder.sourceforge.net/current/java/base64/其他的保存公钥到文件等简单的实现,就不详细说了,看代码吧。==============================================import java.security.*;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.HashMap;import java.util.Map;import javax.crypto.*;import java.io.*;public class Encryptor {private static final String KEY_FILENAME = "c:\\mykey.dat";private static final String OTHERS_KEY_FILENAME = "c:\\Otherskey.dat";// private static final int KEY_SIZE = 1024;// private static final int BLOCK_SIZE = 117;// private static final int OUTPUT_BLOCK_SIZE = 128;private static final int KEY_SIZE = 2048; //RSA key 是多少位的private static final int BLOCK_SIZE = 245; //一次RSA加密操作所允许的最大长度//这个值与 KEY_SIZE 已经padding方法有关。因为 1024的key的输出是128,2048key输出是256字节//可能11个字节用于保存padding信息了,所以最多可用的就只有245字节了。private static final int OUTPUT_BLOCK_SIZE = 256;private SecureRandom secrand;private Cipher rsaCipher;private KeyPair keys;private Map<String, Key> allUserKeys;public Encryptor() throws Exception {try {allUserKeys = new HashMap<String, Key>();secrand = new SecureRandom();//SunJCE Provider 中只支持ECB mode,试了一下只有PKCS1PADDING可以直接还原原始数据,//NOPadding导致解压出来的都是blocksize长度的数据,还要自己处理//参见 http://java.sun.com/javase/6/docs/technotes/guides/security/SunProviders.html#SunJCEProvider////另外根据 Open-JDK-6.b17-src( http://www.docjar.com/html/api/com/sun/crypto/provider/RSACipher.java.html)// 中代码的注释,使用RSA来加密大量数据不是一种标准的用法。所以现有实现一次doFinal调用之进行一个RSA操作,//如果用doFinal来加密超过的一个操作所允许的长度数据将抛出异常。//根据keysize的长度,典型的1024个长度的key和PKCS1PADDING一起使用时//一次doFinal调用只能加密117个byte的数据。(NOPadding 和1024 keysize时128个字节长度)//(2048长度的key和PKCS1PADDING 最多允许245字节一次)//想用来加密大量数据的只能自己用其他办法实现了。可能RSA加密速度比较慢吧,要用AES才行rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();throw e;}ObjectInputStream in;try {in = new ObjectInputStream(new FileInputStream(KEY_FILENAME));} catch (FileNotFoundException e) {if (false == GenerateKeys()){throw e;}LoadKeys();return;}keys = (KeyPair) in.readObject();in.close();LoadKeys();}/** 生成自己的公钥和私钥*/private Boolean GenerateKeys() {try {KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");// secrand = new SecureRandom();// sedSeed之后会造成 生成的密钥都是一样的// secrand.setSeed("chatencrptor".getBytes()); // 初始化随机产生器//key长度至少512长度,不过好像说现在用2048才算比较安全的了keygen.initialize(KEY_SIZE, secrand); // 初始化密钥生成器keys = keygen.generateKeyPair(); // 生成密钥组AddKey("me", EncodeKey(keys.getPublic()));} catch (NoSuchAlgorithmException e) {e.printStackTrace();return false;}ObjectOutputStream out;try {out = new ObjectOutputStream(new FileOutputStream(KEY_FILENAME));} catch (IOException e) {e.printStackTrace();return false;}try {out.writeObject(keys);} catch (IOException e) {e.printStackTrace();return false;} finally {try {out.close();} catch (IOException e) {e.printStackTrace();return false;}}return true;}public String EncryptMessage(String toUser, String Message) throws IOException {Key pubkey = allUserKeys.get(toUser);if ( pubkey == null ){throw new IOException("NoKeyForThisUser") ;}try {//PublicKey pubkey = keys.getPublic();rsaCipher.init(Cipher.ENCRYPT_MODE, pubkey, secrand);//System.out.println(rsaCipher.getBlockSize()); 返回0,非block 加密算法来的?//System.out.println(Message.getBytes("utf-8").length);//byte[] encryptedData = rsaCipher.doFinal(Message.getBytes("utf-8"));byte[] data = Message.getBytes("utf-8");int blocks = data.length / BLOCK_SIZE ;int lastBlockSize = data.length % BLOCK_SIZE ;byte [] encryptedData = new byte[ (lastBlockSize == 0 ? blocks : blocks + 1)* OUTPUT_BLOCK_SIZE];for (int i=0; i < blocks; i++){//int thisBlockSize = ( i + 1 ) * BLOCK_SIZE > data.length ? data.length - i * BLOCK_SIZE : BLOCK_SIZE ;rsaCipher.doFinal(data,i * BLOCK_SIZE, BLOCK_SIZE, encryptedData ,i * OUTPUT_BLOCK_SIZE);}if (lastBlockSize != 0 ){rsaCipher.doFinal(data, blocks * BLOCK_SIZE, lastBlockSize,encryptedData ,blocks * OUTPUT_BLOCK_SIZE);}//System.out.println(encrypted.length); 如果要机密的数据不足128/256字节,加密后补全成为变为256长度的。//数量比较小时,Base64.GZIP产生的长度更长,没什么优势//System.out.println(Base64.encodeBytes(encrypted,Base64.GZIP).length());//System.out.println(Base64.encodeBytes(encrypted).length());//System.out.println (rsaCipher.getOutputSize(30));//这个getOutputSize 只对 输入小于最大的block时才能得到正确的结果。其实就是补全 数据为128/256 字节return Base64.encodeBytes(encryptedData);} catch (InvalidKeyException e) {e.printStackTrace();throw new IOException("InvalidKey") ;}catch (ShortBufferException e) {e.printStackTrace();throw new IOException("ShortBuffer") ;}catch (UnsupportedEncodingException e) {e.printStackTrace();throw new IOException("UnsupportedEncoding") ;} catch (IllegalBlockSizeException e) {e.printStackTrace();throw new IOException("IllegalBlockSize") ;} catch (BadPaddingException e) {e.printStackTrace();throw new IOException("BadPadding") ;}finally {//catch 中 return 或者throw之前都会先调用一下这里}}public String DecryptMessage(String Message) throws IOException {byte[] decoded = Base64.decode(Message);PrivateKey prikey = keys.getPrivate();try {rsaCipher.init(Cipher.DECRYPT_MODE, prikey, secrand);int blocks = decoded.length / OUTPUT_BLOCK_SIZE;ByteArrayOutputStream decodedStream = new ByteArrayOutputStream(decoded.length);for (int i =0 ;i < blocks ; i ++ ){decodedStream.write (rsaCipher.doFinal(decoded,i * OUTPUT_BLOCK_SIZE, OUTPUT_BLOCK_SIZE));}return new String(decodedStream.toByteArray(), "UTF-8");} catch (InvalidKeyException e) {e.printStackTrace();throw new IOException("InvalidKey");} catch (UnsupportedEncodingException e) {e.printStackTrace();throw new IOException("UnsupportedEncoding");} catch (IllegalBlockSizeException e) {e.printStackTrace();throw new IOException("IllegalBlockSize");} catch (BadPaddingException e) {e.printStackTrace();throw new IOException("BadPadding");} finally {// catch 中 return 或者throw之前都会先调用一下这里。}}public boolean AddKey(String user, String key) {PublicKey publickey;try {publickey = DecodePublicKey(key);} catch (Exception e) {return false;}allUserKeys.put(user, publickey);SaveKeys();return true;}private boolean LoadKeys() {BufferedReader input;try {input = new BufferedReader(new InputStreamReader(new FileInputStream(OTHERS_KEY_FILENAME)));} catch (FileNotFoundException e1) {// e1.printStackTrace();return false;}
‘伍’ java中的rsa\des算法的方法
rsa加密解密算法
1978年就出现了这种算法,它是第一个既能用于数据加密
也能用于数字签名的算法。它易于理解和操作,也很流行。算
法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和
Leonard Adleman。但RSA的安全性一直未能得到理论上的证明。
RSA的安全性依赖于大数分解。公钥和私钥都是两个大素数
( 大于 100个十进制位)的函数。据猜测,从一个密钥和密文
推断出明文的难度等同于分解两个大素数的积。
密钥对的产生:选择两个大素数,p 和q 。计算:
n = p * q
然后随机选择加密密钥e,要求 e 和 ( p - 1 ) * ( q - 1 )
互质。最后,利用Euclid 算法计算解密密钥d, 满足
e * d = 1 ( mod ( p - 1 ) * ( q - 1 ) )
其中n和d也要互质。数e和
n是公钥,d是私钥。两个素数p和q不再需要,应该丢弃,不要让任
何人知道。 加密信息 m(二进制表示)时,首先把m分成等长数据
块 m1 ,m2,..., mi ,块长s,其中 2^s <= n, s 尽可能的大。对
应的密文是:
ci = mi^e ( mod n ) ( a )
解密时作如下计算:
mi = ci^d ( mod n ) ( b )
RSA 可用于数字签名,方案是用 ( a ) 式签名, ( b )
式验证。具体操作时考虑到安全性和 m信息量较大等因素,一般是先
作 HASH 运算。
RSA 的安全性。
RSA的安全性依赖于大数分解,但是否等同于大数分解一直未能得到理
论上的证明,因为没有证明破解RSA就一定需要作大数分解。假设存在
一种无须分解大数的算法,那它肯定可以修改成为大数分解算法。目前,
RSA的一些变种算法已被证明等价于大数分解。不管怎样,分解n是最显
然的攻击方法。现在,人们已能分解140多个十进制位的大素数。因此,
模数n必须选大一些,因具体适用情况而定。
RSA的速度:
由于进行的都是大数计算,使得RSA最快的情况也比DES慢上100倍,无论
是软件还是硬件实现。速度一直是RSA的缺陷。一般来说只用于少量数据
加密。
RSA的选择密文攻击:
RSA在选择密文攻击面前很脆弱。一般攻击者是将某一信息作一下伪装
(Blind),让拥有私钥的实体签署。然后,经过计算就可得到它所想要的信
息。实际上,攻击利用的都是同一个弱点,即存在这样一个事实:乘幂保
留了输入的乘法结构:
( XM )^d = X^d *M^d mod n
前面已经提到,这个固有的问题来自于公钥密码系统的最有用的特征
--每个人都能使用公钥。但从算法上无法解决这一问题,主要措施有
两条:一条是采用好的公钥协议,保证工作过程中实体不对其他实体
任意产生的信息解密,不对自己一无所知的信息签名;另一条是决不
对陌生人送来的随机文档签名,签名时首先使用One-Way HashFunction
对文档作HASH处理,或同时使用不同的签名算法。在中提到了几种不
同类型的攻击方法。
RSA的公共模数攻击。
若系统中共有一个模数,只是不同的人拥有不同的e和d,系统将是危险
的。最普遍的情况是同一信息用不同的公钥加密,这些公钥共模而且互
质,那末该信息无需私钥就可得到恢复。设P为信息明文,两个加密密钥
为e1和e2,公共模数是n,则:
C1 = P^e1 mod n
C2 = P^e2 mod n
密码分析者知道n、e1、e2、C1和C2,就能得到P。
因为e1和e2互质,故用Euclidean算法能找到r和s,满足:
r * e1 + s * e2 = 1
假设r为负数,需再用Euclidean算法计算C1^(-1),则
( C1^(-1) )^(-r) * C2^s = P mod n
另外,还有其它几种利用公共模数攻击的方法。总之,如果知道给定模数
的一对e和d,一是有利于攻击者分解模数,一是有利于攻击者计算出其它
成对的e’和d’,而无需分解模数。解决办法只有一个,那就是不要共享
模数n。
RSA的小指数攻击。 有一种提高
RSA速度的建议是使公钥e取较小的值,这样会使加密变得易于实现,速度
有所提高。但这样作是不安全的,对付办法就是e和d都取较大的值。
RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作。
RSA是被研究得最广泛的公钥算法,从提出到现在已近二十年,经历了各
种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。
RSA的安全性依赖于大数的因子分解,但并没有从理论上证明破译RSA的难
度与大数分解难度等价。即RSA的重大缺陷是无法从理论上把握它的保密性
能如何,而且密码学界多数人士倾向于因子分解不是NPC问题。
RSA的缺点主要有:
A)产生密钥很麻烦,受到素数产生技术的限制,因而难以做到一次
一密。B)分组长度太大,为保证安全性,n 至少也要 600 bits
以上,使运算代价很高,尤其是速度较慢,较对称密码算法慢几个数量级;
且随着大数分解技术的发展,这个长度还在增加,不利于数据格式的标准化。
目前,SET(Secure Electronic Transaction)协议中要求CA采用2048比特长
的密钥,其他实体使用1024比特的密钥。
参考资料:http://superpch.josun.com.cn/bbs/PrintPost.asp?ThreadID=465
CRC加解密算法
http://www.bouncycastle.org/
‘陆’ 关于java中rsa的问题
【实例下载】本文介绍RSA2加密与解密,RSA2是RSA的加强版本,在密钥长度上采用2048, RSA2比RSA更安全,更可靠, 本人的另一篇文章RSA已经发表,有想了解的可以点开下面的RSA文章
‘柒’ c#怎么调用java生成的RSA 公钥进行加密
.NET无法调用JAVA产生的RSA公钥,必须将RSA算法在.NET里面重写才行,在.NET里面RSA的公钥长度是128位的,但是你给出的JAVA公钥却是159位长度,非常的不标准,公钥长度不满足128的肯定无法给.NET使用。
这里最多帮做个对应解析,数据是肯定无法用的:
将java的RSA公钥最后四个字母AQAB分割开,用.NET的xml格式表示就是
<RSAKeyValue><Molus>
/qp
jLFfDCu3qytxf+/IoCYE
+Hf4hsEDUKV2kkhRJsnwwID</Molus><Exponent>AQAB</Exponent>
</RSAKeyValue>
这里的数据都是用的BASE64编码,你用BASE64解码后可以得到byte[],就可以看到密钥长度了,实际密钥要转换为BigInteger后才能参与RSA核心运算
‘捌’ 如何用java实现128位密钥的RSA算法
importjavax.crypto.Cipher;
importsun.misc.BASE64Decoder;
importsun.misc.BASE64Encoder;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.ObjectInputStream;
importjava.io.ObjectOutputStream;
importjava.security.Key;
importjava.security.KeyPair;
importjava.security.KeyPairGenerator;
importjava.security.SecureRandom;
publicclassRSA_Encrypt{
/**指定加密算法为DESede*/
privatestaticStringALGORITHM="RSA";
/**指定key的大小*/
privatestaticintKEYSIZE=128;
/**指定公钥存放文件*/
privatestaticStringPUBLIC_KEY_FILE="PublicKey";
/**指定私钥存放文件*/
privatestaticStringPRIVATE_KEY_FILE="PrivateKey";
//privatestaticStringPUBLIC_KEY_FILE="D://PublicKey.a";
//privatestaticStringPRIVATE_KEY_FILE="D://PrivateKey.a";
/**
*生成密钥对
*/
()throwsException{
/**RSA算法要求有一个可信任的随机数源*/
SecureRandomsr=newSecureRandom();
/**为RSA算法创建一个KeyPairGenerator对象*/
KeyPairGeneratorkpg=KeyPairGenerator.getInstance(ALGORITHM);
/**利用上面的随机数据源初始化这个KeyPairGenerator对象*/
kpg.initialize(KEYSIZE,sr);
/**生成密匙对*/
KeyPairkp=kpg.generateKeyPair();
/**得到公钥*/
KeypublicKey=kp.getPublic();
/**得到私钥*/
KeyprivateKey=kp.getPrivate();
/**用对象流将生成的密钥写入文件*/
ObjectOutputStreamoos1=newObjectOutputStream(newFileOutputStream(PUBLIC_KEY_FILE));
ObjectOutputStreamoos2=newObjectOutputStream(newFileOutputStream(PRIVATE_KEY_FILE));
oos1.writeObject(publicKey);
oos2.writeObject(privateKey);
/**清空缓存,关闭文件输出流*/
oos1.close();
oos2.close();
}
/**
*加密方法
*source:源数据
*/
publicstaticStringencrypt(Stringsource)throwsException{
generateKeyPair();
/**将文件中的公钥对象读出*/
ObjectInputStreamois=newObjectInputStream(newFileInputStream(PUBLIC_KEY_FILE));
Keykey=(Key)ois.readObject();
ois.close();
/**得到Cipher对象来实现对源数据的RSA加密*/
Ciphercipher=Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE,key);
byte[]b=source.getBytes();
/**执行加密操作*/
byte[]b1=cipher.doFinal(b);
BASE64Encoderencoder=newBASE64Encoder();
returnencoder.encode(b1);
}
/**
*解密算法
*cryptograph:密文
*/
publicstaticStringdecrypt(Stringcryptograph)throwsException{
/**将文件中的私钥对象读出*/
ObjectInputStreamois=newObjectInputStream(newFileInputStream(PRIVATE_KEY_FILE));
Keykey=(Key)ois.readObject();
/**得到Cipher对象对已用公钥加密的数据进行RSA解密*/
Ciphercipher=Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE,key);
BASE64Decoderdecoder=newBASE64Decoder();
byte[]b1=decoder.decodeBuffer(cryptograph);
/**执行解密操作*/
byte[]b=cipher.doFinal(b1);
returnnewString(b);
}
publicstaticvoidmain(String[]args){
try{
Stringsource="HelloWorld!";//要加密的字符串
Stringcryptograph=encrypt(source);
System.out.println(cryptograph);
Stringtarget=decrypt(cryptograph);//解密密文
System.out.println(target);
}catch(Exceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}//生成的密文
}
}
‘玖’ java生成rsa密钥,c++可以直接使用密钥解密吗
可以的,RSA加密解密有一套规则的,不同的语言都会遵循,只是实现的方式不一样。
用对应的的公钥就可以进行解密