RSA算法出现于1978年,算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman,是第一个既能用于数据加密也能用于数字签名的算法。这种加密算法的特点主要是密钥的变化,与DES只有一个密钥相比较,RSA同时有两把钥匙,公钥与私钥。同时支持数字签名。数字签名的意义在于,对传输过来的数据进行校验,确保数据在传输工程中不被修改。
RSA加密、解密、数字签名流程:
1、A构建密钥对:公钥、私钥,将公钥公布给B,将私钥保留。
2、A使用私钥加密数据,然后用私钥对加密后的数据签名,发送给B签名以及加密后的数据;B使用公钥、签名来验证待解密数据是否有效,如果有效使用公钥对数据解密。
3、B使用公钥加密数据,向A发送经过加密后的数据;A获得加密数据,通过私钥解密。
应用:由于RSA是一种既可用于数据的加密和解密,也可以进行数字签名的算法,所以也可以用于软件的许可文件的注册或者sso的登录信息加密。
example:
初始化密钥:
// KeyPair生成器
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen .genKeyPair();
PublicKey publicKey = keyPair.getPublic(); // 公钥
PrivateKey privateKey = keyPair.getPrivate(); // 私钥
// 将公钥写成文件,便于存放和迁移
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
RSAPublicKeySpec rsaPublicSpec = (RSAPublicKeySpec)keyFactory .getKeySpec(publicKey, RSAPublicKeySpec.class);
PublicKeySpec licenseKey = new PublicKeySpec(rsaPublicSpec);
String storePath = "d:/";
File licensePath = new File(storePath);
File keyPath = new File(licensePath.getAbsolutePath().substring(0,
licensePath.getAbsolutePath().lastIndexOf(File.separator)) + File.separator + "public.key");
FileOutputStream fKey = new FileOutputStream(keyPath);
ObjectOutputStream oos = new ObjectOutputStream(fKey);
oos.writeObject(licenseKey);
oos.close();
// 使用私钥对文件进行数字签名
String srcstr = "<user><username></username><password></password></user>";
byte[] input = srcstr.getBytes();
Signature s = Signature.getInstance("MD5withRSA");
s.initSign(privateKey);
s.update(input);
byte[] result = s.sign(); // 生成的签名结果
// 用公钥进行数字签名校验
byte[] data = srcstr.getBytes(); // 待校验文件
byte[] signature = result; // 数字签名证书文件流
KeyFactory keyfactory = KeyFactory.getInstance("RSA");
FileInputStream fis = new FileInputStream(new File(publicKeySpecPath));
ObjectInputStream ois = new ObjectInputStream(fis);
PublicKeySpec publicKeySpec = (PublicKeySpec) ois.readObject();
PublicKey publicKey = keyfactory.generatePublic(publicKeySpec.genRSAPublicKeySpec());
Signature s = Signature.getInstance("MD5withRSA");
s.initVerify(publicKey);
s.update(data);
boolean isRight = s.verify(signature);
// 用公钥加密
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] data = srcstr.getBytes();
// publicKeySpecPath为生成公钥的文件
FileInputStream fis = new FileInputStream(new File(publicKeySpecPath));
ObjectInputStream ois = new ObjectInputStream(fis);
PublicKeySpec publicKeySpec = (PublicKeySpec) ois.readObject();
PublicKey publicKey = keyfactory.generatePublic(publicKeySpec.genRSAPublicKeySpec()); // 取得公钥
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptdata = cipher.doFinal(data);
// 用私钥解密
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] data = srcstr.getBytes();
// publicKeySpecPath为生成私钥的文件
byte[] keyBytes = key.getEncoded();
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptdata = cipher.doFinal(data);
// 用私钥加密
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] data = srcstr.getBytes();
// publicKeySpecPath为生成私钥的文件
byte[] keyBytes = privateKey.getEncoded();
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] decryptdata = cipher.doFinal(data);
// 用公钥解密
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] data = srcstr.getBytes();
// publicKeySpecPath为生成公钥的文件
FileInputStream fis = new FileInputStream(new File(publicKeySpecPath));
ObjectInputStream ois = new ObjectInputStream(fis);
PublicKeySpec publicKeySpec = (PublicKeySpec) ois.readObject();
PublicKey publicKey = keyfactory.generatePublic(publicKeySpec.genRSAPublicKeySpec()); // 取得公钥
// ===================也可以直接通过PublicKey取得==================
byte[] keyBytes = publicKey.getEncoded();
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
Key publicKey = keyFactory.generatePublic(pkcs8KeySpec);
// ================================================================
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] encryptdata = cipher.doFinal(data);