文章16 | 阅读 7013 | 点赞0
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战。RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
package com.jianggujin.codec;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import com.jianggujin.codec.util.JCipherInputStream;
import com.jianggujin.codec.util.JCipherOutputStream;
import com.jianggujin.codec.util.JCodecException;
/** * RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard * Adleman)一起提出的。1987年首次公布,当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。 * RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。 * 今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长, * 用RSA加密的信息实际上是不能被解破的。但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战。 * RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。 * * 1、甲方构建密钥对儿,将公钥公布给乙方,将私钥保留。 * 2、甲方使用私钥加密数据,然后用私钥对加密后的数据签名,发送给乙方签名以及加密后的数据;乙方使用公钥、签名来验证待解密数据是否有效, * 3、如果有效使用公钥对数据解密。 乙方使用公钥加密数据,向甲方发送经过加密后的数据;甲方获得加密数据,通过私钥解密。 * * @author jianggujin * */
public class JRSA {
private static final String ALGORITHM = "RSA";
/** * RSA签名算法 * * @author jianggujin * */
public static enum JRSASignatureAlgorithm {
MD2withRSA, MD5withRSA, SHA1withRSA, SHA224withRSA, SHA256withRSA, SHA384withRSA, SHA512withRSA;
public String getName() {
return this.name();
}
}
/** * 初始化密钥 * * @return */
public static KeyPair initKey() {
return initKey(1024);
}
/** * 初始化密钥 * * @param keySize * @return */
public static KeyPair initKey(int keySize) {
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALGORITHM);
keyPairGen.initialize(keySize);
return keyPairGen.generateKeyPair();
} catch (Exception e) {
throw new JCodecException(e);
}
}
/** * 签名 * * @param data * @param privateKey * @param signatureAlgorithm * @return */
public static byte[] sign(byte[] data, byte[] privateKey, String signatureAlgorithm) {
try {
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance(signatureAlgorithm);
signature.initSign(priKey);
signature.update(data);
return signature.sign();
} catch (Exception e) {
throw new JCodecException(e);
}
}
/** * 验签 * * @param data * @param publicKey * @param sign * @param signatureAlgorithm * @return */
public static boolean verify(byte[] data, byte[] publicKey, byte[] sign, String signatureAlgorithm) {
try {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(signatureAlgorithm);
signature.initVerify(pubKey);
signature.update(data);
return signature.verify(sign);
} catch (Exception e) {
throw new JCodecException(e);
}
}
/** * 公钥加密 * * @param data * @param publicKey * @return */
public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) {
Cipher cipher = getEncryptCipherByPublicKey(publicKey);
try {
return cipher.doFinal(data);
} catch (Exception e) {
throw new JCodecException(e);
}
}
/** * 私钥加密 * * @param data * @param privateKey * @return */
public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) {
Cipher cipher = getEncryptCipherByPrivateKey(privateKey);
try {
return cipher.doFinal(data);
} catch (Exception e) {
throw new JCodecException(e);
}
}
/** * 包裹输出流,包裹后的输出流为公钥加密输出流 * * @param out * @param publicKey * @return */
public static OutputStream wrapByPublicKey(OutputStream out, byte[] publicKey) {
Cipher cipher = getEncryptCipherByPublicKey(publicKey);
return new JCipherOutputStream(cipher, out);
}
/** * 包裹输出流,包裹后的输出流为私钥加密输出流 * * @param out * @param privateKey * @return */
public static OutputStream wrapByPrivateKey(OutputStream out, byte[] privateKey) {
Cipher cipher = getEncryptCipherByPrivateKey(privateKey);
return new JCipherOutputStream(cipher, out);
}
/** * 获得公钥加密模式的{@link Cipher} * * @param publicKey * @return */
public static Cipher getEncryptCipherByPublicKey(byte[] publicKey) {
return getCipherByPublicKey(publicKey, Cipher.ENCRYPT_MODE);
}
/** * 获得私钥加密模式的{@link Cipher} * * @param privateKey * @return */
public static Cipher getEncryptCipherByPrivateKey(byte[] privateKey) {
return getCipherByPrivateKey(privateKey, Cipher.ENCRYPT_MODE);
}
/** * 公钥解密 * * @param data * @param publicKey * @return */
public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) {
Cipher cipher = getDecryptCipherByPublicKey(publicKey);
try {
return cipher.doFinal(data);
} catch (Exception e) {
throw new JCodecException(e);
}
}
/** * 私钥解密 * * @param data * @param privateKey * @return */
public static byte[] decryptByPrivateKey(byte[] data, byte[] privateKey) {
Cipher cipher = getDecryptCipherByPrivateKey(privateKey);
try {
return cipher.doFinal(data);
} catch (Exception e) {
throw new JCodecException(e);
}
}
/** * 包裹输入流,原输入流为公钥加密数据输入流 * * @param in * @param publicKey * @return */
public static InputStream wrapByPublicKey(InputStream in, byte[] publicKey) {
Cipher cipher = getDecryptCipherByPublicKey(publicKey);
return new JCipherInputStream(cipher, in);
}
/** * 包裹输入流,原输入流为私钥加密数据输入流 * * @param in * @param privateKey * @return */
public static InputStream wrapByPrivateKey(InputStream in, byte[] privateKey) {
Cipher cipher = getDecryptCipherByPrivateKey(privateKey);
return new JCipherInputStream(cipher, in);
}
/** * 获得公钥解密模式的{@link Cipher} * * @param publicKey * @return */
public static Cipher getDecryptCipherByPublicKey(byte[] publicKey) {
return getCipherByPublicKey(publicKey, Cipher.DECRYPT_MODE);
}
/** * 获得私钥解密模式的{@link Cipher} * * @param privateKey * @return */
public static Cipher getDecryptCipherByPrivateKey(byte[] privateKey) {
return getCipherByPrivateKey(privateKey, Cipher.DECRYPT_MODE);
}
private static Cipher getCipherByPublicKey(byte[] publicKey, int opmode) {
try {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKey);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(opmode, publicK);
return cipher;
} catch (Exception e) {
throw new JCodecException(e);
}
}
private static Cipher getCipherByPrivateKey(byte[] privateKey, int opmode) {
try {
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(opmode, privateK);
return cipher;
} catch (Exception e) {
throw new JCodecException(e);
}
}
}
测试代码:
package com.jianggujin.codec.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyPair;
import org.junit.Test;
import com.jianggujin.codec.JBase64;
import com.jianggujin.codec.JBase64.JEncoder;
import com.jianggujin.codec.JRSA;
import com.jianggujin.codec.JRSA.JRSASignatureAlgorithm;
public class RSATest {
String str = "jianggujin";
File file = new File(getClass().getSimpleName() + ".dat");
@Test
public void test() throws Exception {
System.out.println("原串:" + str);
JEncoder encoder = JBase64.getEncoder();
KeyPair keyPair = JRSA.initKey();
byte[] privateKey = keyPair.getPrivate().getEncoded();
byte[] publicKey = keyPair.getPublic().getEncoded();
System.out.println("私钥:" + encoder.encodeToString(privateKey, "UTF-8"));
System.out.println("公钥:" + encoder.encodeToString(publicKey, "UTF-8"));
for (JRSASignatureAlgorithm algorithm : JRSASignatureAlgorithm.values()) {
System.out.println("-----------------------------------------");
System.out.println("签名算法:" + algorithm.getName());
byte[] signed = JRSA.sign(str.getBytes(), privateKey, algorithm.getName());
System.out.println("签名:" + encoder.encodeToString(signed, "UTF-8"));
boolean verify = JRSA.verify(str.getBytes(), publicKey, signed, algorithm.getName());
System.out.println("验签:" + verify);
}
byte[] encrypt = JRSA.encryptByPrivateKey(str.getBytes(), privateKey);
System.out.println("私钥加密:" + encoder.encodeToString(encrypt, "UTF-8"));
System.out.println("公钥解密:" + new String(JRSA.decryptByPublicKey(encrypt, publicKey)));
System.out.print("输出流私钥加密:" + file.getAbsolutePath());
OutputStream out = JRSA.wrapByPrivateKey(new FileOutputStream(file), privateKey);
out.write(str.getBytes());
out.flush();
out.close();
System.out.println();
System.out.print("输入流公钥解密:");
InputStream in = JRSA.wrapByPublicKey(new FileInputStream(file), publicKey);
byte[] buffer = new byte[1024];
int len = in.read(buffer);
System.out.println(new String(buffer, 0, len));
encrypt = JRSA.encryptByPublicKey(str.getBytes(), publicKey);
System.out.println("公钥加密:" + encoder.encodeToString(encrypt, "UTF-8"));
System.out.println("私钥解密:" + new String(JRSA.decryptByPrivateKey(encrypt, privateKey)));
System.out.print("输出流公钥加密:" + file.getAbsolutePath());
out = JRSA.wrapByPublicKey(new FileOutputStream(file), publicKey);
out.write(str.getBytes());
out.flush();
out.close();
System.out.println();
System.out.print("输入流私钥解密:");
in = JRSA.wrapByPrivateKey(new FileInputStream(file), privateKey);
len = in.read(buffer);
System.out.println(new String(buffer, 0, len));
}
}
测试结果:
原串:jianggujin
私钥:MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIg0EUOutbMRJDuNNCJT97QPK2rrTYFBLBu9vXk6upCvTCn9yZA2M2wNrCv39hVGbXXHSxs2zXpYlWR1IKUvWppQfIscckB3sXJIvvR25xWJWKJSOrbddNKXyvdLjDgor13QVaXJECZJMXsDLFw9kJ+GXz5nzQ43qHyefzLC2YkdAgMBAAECgYAPdlm/ZUYbXgbO++i/POkR9+bl7HCQC+YGADRSXuhvJHdxDO6lAII18hdppmy5XZVvmYBdRottKEFNdj6OgiG22GT2qe0voBaTFpnMEtTNJWJsDjRfnl369XQFC8uPfYF9Qn1nYBSTS+1pxyJSybZkkmAv99sKh1WTHFd+CdhZwQJBANBty698Yy5IXyHHs56EMC81DJjmmZ+WYpRqmUJTSyoCmW9KTztVStX42RMG0tLYOPstbJ0M6rr0G9JVWjJJ3OcCQQCnSjz8hKzu6LC0Arj6fVKPAWboHAjHCQ8AG71JEFkjhvXKYW7dJYua1ePYm4+b8+rr7Ovw6Mvesl36mCWYDIVbAkBkNKU8lTzJv5mdD/nXOA5CY+rOh+9Lvm1elXFhZdI5PE6wJrW4/OShwqX6c8lf/PxIJiqVxuQDReEqWkam7sP5AkA19u/HcbErfGqMFxi+zTCVqxkcJPb75cMuAMTFzf1DRaUCPP37XsIzF25hkIT6BOwyYQIXe7FQTG+eh/gQnXFjAkAGRVxiTmzpSchUjuKOXgS1zjVd4oYqiP4UXQRrrCTmhldkLIEVhm+zsf+t6o01aS/Bc5pJcAUElYvW2AiNFDRx
公钥:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCINBFDrrWzESQ7jTQiU/e0Dytq602BQSwbvb15OrqQr0wp/cmQNjNsDawr9/YVRm11x0sbNs16WJVkdSClL1qaUHyLHHJAd7FySL70ducViViiUjq23XTSl8r3S4w4KK9d0FWlyRAmSTF7AyxcPZCfhl8+Z80ON6h8nn8ywtmJHQIDAQAB
—————————————–
签名算法:MD2withRSA
签名:U1gqODkxXTwQJOqLqHRV3S4gbhIxC036k+LpG4W4kcxhZogDrZxtfFpisXSqgp3DSw+PGgKy6rT7RLIExCi1Qvdh23vmB2Fe7F6yHQ34rhm1NNnbye9ELro7m45t3DP3doY/6qXtGW8N/M5aBs2Mwh2r8uB0KZxE53VvXdWJVac=
验签:true
—————————————–
签名算法:MD5withRSA
签名:AHd5QQTqZgDlXFmS1YF8PSZI7d4gGB50vMnFELwdADZ49PVuMKkiPDHsao5g//6p6e5f13PIuUgZYrOPSyifSSKSy7kT/zhjh7quMUtK3xeNspOQH2pXI1PlU8duY3aejeYfqBQ5rc+L+tFk/B29H/WmtlGVImWV62aCvt8YduY=
验签:true
—————————————–
签名算法:SHA1withRSA
签名:g0bsq25OrrngrAntLNdsXDixO3Zo+DZOe1xdT4n1FLiQDkvv5NvS/HM5jyl8pkZa2VV+536oyRKDrqyLQR8bkbsnjWae9aBF2JweRIXGo4sVm1csQglrz52t4W4/gF0oWqlJhHucTClPdX1XGMBMnRjfXHM01F7QdN1Rezc+1xk=
验签:true
—————————————–
签名算法:SHA224withRSA
签名:QeD1a4s6gaEee9bDTakjergCfwqKfX7x89D8e7GY6rroMf8d3g9JCZkt4PePbhWdorVsUiDexTkHTCXcAGXHu6l9Lxh97O7S/H090i24JLThhVLKBLRZDHidLzfclbvqBky7Fk2PSSlpuxARmxbbc3N5J1a0Sqk9NnMO0AMvgMI=
验签:true
—————————————–
签名算法:SHA256withRSA
签名:FQAliYG2d1rJi+iShdrTuxAQ+TYaghbCcQ0WuvYwmMHf5mz8ilMgGXxuRM75TRLy/LX/Si6uec+gnfB3vC8ep+qWOPh/HXdmofEOpKih+Z3/iy8zvRH+PpuNSwwCifqgGXHzA/thaw93hTx+Ji5qnl8PUn6Rt/cHYsx5takQXGQ=
验签:true
—————————————–
签名算法:SHA384withRSA
签名:ZuD/Cg8DFHZUzj3h61kLHDDU30xBjgq9x4xvwmSkqyEddQfyr2MPAIj4PpiAXhSNpkmKtm+tC0VQseXzfH2tE0Ylzilwun3rfl/Th83bwB9uG4i0xU0vYQkN7flCS7LwbTc/XQc+i3bpSYdJ7/x34kSYEC+K9KMI3n55CNOEEiw=
验签:true
—————————————–
签名算法:SHA512withRSA
签名:euYju1srslIb3yWTM7sAQZIARvgTPKlfd7hCWQ3a6GMK9272kLQWi4b4TQe4gKbMBh6KmMhXJNdRYrEk1AM61d46YHyGqh0TvsaLrk66wemtILBogJzmEFiOpXbPbEtIuOfQMzc+NPDoLDhdCcLJ1ZhSid6a7eR0mb4aYqdJbfY=
验签:true
私钥加密:a4HdJteeI56m1aYbulriTzyvheKlarumWNEesksoO6iQqWNUPHtqe6GfZJuAdu6YOcmf9xctPdRAnTmTTC9pwKlfr0FcIdsheV05ZmdnkfkW5jd73aeP5MCVSiS/gZ74sECB/q3ByJxu+1kHy4dGx920lra7K9iwT0KtaRFFnwI=
公钥解密:jianggujin
输出流私钥加密:F:\workspace\java\eclipse\JCodec\RSATest.dat
输入流公钥解密:jianggujin
公钥加密:FD8wt6qDlmEdGt58ez0YnbZom9+756BOIF701NosVtpYTnG7agyfxdsq486PV5BTeiFU9zH+KKJkh4bXBDFUA0UV+YiLaeX+a/mScG5R7teoqiYpQ63pLhRnD6eFBbbcM+i5oEW3maM9si5nbWjEZ4aYxxQaz4C16Tl9Yeg9OPY=
私钥解密:jianggujin
输出流公钥加密:F:\workspace\java\eclipse\JCodec\RSATest.dat
输入流私钥解密:jianggujin
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/jianggujin/article/details/50537185
内容来源于网络,如有侵权,请联系作者删除!