package com.gmc.algorithms;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.util.ArrayList;
import javax.crypto.Cipher;
import com.gmc.algorithms.Base64;
import com.gmc.crypto.AsymmetryEncrypt;
/**
* RSA非对称加密算法的实现类,实现了对字符串、文件、数据流的加密(公钥加密)、解密(私钥解密)、数字签名(私钥加密)和签名验证(公钥验证)功能
* 此加密算法操作的数据长度不能大于117位。
* @author wanna
*
*/
public class RSATools implements AsymmetryEncrypt
{
private final static String algorithm = "RSA"; //非对称加密算法RSA
public static final String SIGNALGORITHM = "SHA1WithRSA"; // 数字签名算法
private KeyPair rsaKeyPair; //RSA算法的密钥对
private PublicKey pubKey; //公钥
private PrivateKey priKey; // 私钥
private FileInputStream fis;
private FileOutputStream fos;
public RSATools()
{
}
/**
* 解密
* @param cipherText 密文信息
* @param key 解密操作所需的私钥,如果为null,则不能执行解密操作
* @return 解密后的明文信息
* @throws Exception
*/
public String decrypt(byte[] cipherText, Key key) throws Exception
{
if (cipherText == null || cipherText.length == 0)
{
return null;
}
if (key == null)
{
return null;
}
this.priKey = (PrivateKey) key; //设置解密所用的私钥
byte[] input = Base64.decode(cipherText); //用Base64对密文解码
return new String(this.basicDecrypt(input));
}
/**
* 解密
*
* @param cipherText 密文信息
* @param key 解密操作所需的私钥,如果为null,则不能执行解密操作
* @return 解密后的明文信息 字符串形式
* @throws Exception
*/
public String decrypt(String cipherText, Key key) throws Exception
{
if (cipherText == null)
{
return null;
}
if (key == null)
{
return null;
}
this.priKey = (PrivateKey) key;
byte[] input = Base64.decode(cipherText);
return new String(this.basicDecrypt(input));
}
/**
* 解密 对文件进行解密操作,文件的扩展名必须为.fjm,解密后的明文文件所在路径与密文相同。
* 例: 密文 :F:\1.txt.fjm
* 明文: F:\1.txt
* @param cipherFile 待解密的文件
* @param key 解密所用的私钥
* @return 以文件形式存储的明文信息
* @throws Exception
*/
public File decrypt(File cipherFile, Key key) throws Exception
{
if (cipherFile == null)
{
return null;
}
if (!cipherFile.exists() || cipherFile.isDirectory())
{
return null;
}
if (key == null)
{
return null;
}
this.priKey = (PrivateKey) key;
try
{
String strPath = cipherFile.getPath();
if (!strPath.substring(strPath.length() - 4).toLowerCase().equals(".fjm")) //判断文件的扩展名是否是fjm,不是停止解密操作
{
return null;
}
fis = new FileInputStream(cipherFile);
byte[] input = this.getByteFromStream(fis); //获取文件流中的密文数据
byte[] output = this.basicDecrypt(input); //解密
String outFilePath = strPath.substring(strPath.length() - 4);
File fileOut = new File(outFilePath); //存储明文信息的文件
fos = new FileOutputStream(fileOut);
for (int i = 0; i < output.length; i++)
{
fos.write((int) output[i]);
}
System.out.println("解密成功");
return fileOut;
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
this.closeStream();
}
return null;
}
/**
* 解密 对输入流中的密文信息进行解密
* @param cipherText 存有密文数据的输入流
* @param key 解密的私钥,如果为null,则不能进行解密操作。
* @param plainPath 存储解密后的明文信息的文件路径
* @return 指定路径下,存有明文信息的文件
* @throws Exception
*/
public File decrypt(InputStream cipherText, Key key,String plainPath) throws Exception
{
if(cipherText==null||key==null)
{
return null;
}
if(plainPath==null||plainPath.equals(""))
{
return null;
}
this.priKey= (PrivateKey)key;
byte[] input = this.getByteFromStream(cipherText);
byte[] output = this.basicDecrypt(input);
File outputFile = new File(plainPath);
fos = new FileOutputStream(outputFile);
for(int i=0;i<output.length;i++)
{
fos.write((int)output[i]);
}
System.out.println("解密成功");
return outputFile;
}
/**
* 加密
* @param plainText 明文
* @param key 加密所用的公钥,如果为null则自动生成一个密钥对,使用其中的公钥进行加密
* @return 加密后的密文,字符串形式
* @throws Exception
*/
public String encrypt(byte[] plainText, Key key) throws Exception
{
if (plainText == null || plainText.length == 0)
{
return null;
}
this.setKeyPairWhenEncrypt(key);
return Base64.encode(this.basicEncrypt(plainText));
}
/**
* 加密
* @param plainText 明文
* @param key 加密所用的公钥,如果为null则自动生成一个密钥对,使用其中的公钥进行加密
* @return 加密后的密文,字符串形式
* @throws Exception
*/
public String encrypt(String plainText, Key key) throws Exception
{
if (plainText == null)
{
return null;
}
this.setKeyPairWhenEncrypt(key);
byte[] input = plainText.getBytes();
return Base64.encode(this.basicEncrypt(input));
}
/**
* 加密文件,加密后在file路径下生成一扩展名为的文件,用于存储密文信息
* 例: 明文: F:\1.txt
* 密文文件为:F:\1.txt.fjm
* @param file 待加密的文件
* @param key 加密所用的公钥,如果为null则自动生成一个密钥对,使用其中的公钥进行加密
* @return 扩展名为.fjm、存有密文信息的文件
* @throws Exception
*/
public File encrypt(File file, Key key) throws Exception
{
if (file == null)
{
return null;
}
if (!file.exists() || file.isDirectory())
{
return null;
}
try
{
this.setKeyPairWhenEncrypt(key);
fis = new FileInputStream(file);
byte[] input = this.getByteFromStream(fis);
byte[] output = this.basicEncrypt(input);
String cipherFilePath = file.getPath() + ".fjm"; //在 file路径下创建一扩展名为.fjm的文件
File fileOut = new File(cipherFilePath);
fos = new FileOutputStream(fileOut);
for (int i = 0; i < output.length; i++)
{
fos.write((int) output[i]);
}
System.out.println("加密成功");
return fileOut;
}
catch (Exception e)
{
e.printStackTrace();
throw e;
}
finally
{
this.closeStream();
}
}
/**
* 加密
* @param plainText 存有明文信息的输入流
* @param key 加密所需公钥Key如果传null,则自动生成一个密钥对,用其中的公钥进行加密
* @param cipherPath 加密后,存放密文信息的文件路径
* @return 存有密文件信息的文件
* @throws Exception
*/
public File encrypt(InputStream plainText, Key key,String cipherPath) throws Exception
{
if(plainText==null)
{
return null;
}
if(cipherPath==null||cipherPath.equals(""))
{
return null;
}
try
{
this.setKeyPairWhenEncrypt(key);
byte[] input = this.getByteFromStream(plainText);
byte[] output = this.basicEncrypt(input);
File outputFile = new File(cipherPath);
fos = new FileOutputStream(outputFile);
for(int i = 0;i<output.length;i++)
{
fos.write((int)output[i]);
}
System.out.println("加密成功");
return outputFile;
}catch(Exception e)
{
e.printStackTrace();
throw e;
}
finally
{
this.closeStream();
}
}
/**
* 数字签名
* @param plainText 明文
* @param key 数字签名所需私钥,如果key为null,则自动为其生成一个密钥对,用其私钥进行签名
* @return 字符串形式的签名信息
* @throws Excepti