Rijndacel基于口令的对称加密
来源:互联网 发布:python开发聊天机器人 编辑:程序博客网 时间:2024/05/21 01:57
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.Key;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/*
*采用ASE加密算法(也就是Rijndacel)加密文件,对文件解密需要同样的密钥
*通过用口令对密钥进行加密,并把加密后的密钥存储在文件中
* CipherStream文件加密器,基与口令的密钥加密,加密的密钥存储在
* 一个二进制文件中,一般的软件无法打开.这儿首次通过判段数组中是
*第一个数据判断是进行创建密钥还是其他,注意基于口令的加密口令必须
*是字符数组。
*
*/
/* 注意:最后一个导入的包从www.bouncycastle.org中下载,完整版crypto-147
* 需要文件crypto-147\jars\jce-jdk13-147.jar放到jre\lib\ext不过我是
* 直接放到创建文件夹的lib下面
* 配置java.security文件使提供者可以使用
* 步骤jre\lib\security下打开java.security文件
* security.provider.11=org.bouncycastle.jce.provider.BouncyCastleProvider
*/ 貌似也没什么效果
public class FileEncrytor {
private int iteration = 100;
private String Key_Filename = "RijndaelKey.bin";//二进制文件,必须用特殊软件才
能打开
public void ManageCipherStream(String arg[]) throws Exception{
char psd[]=arg[1].toCharArray();
Security.addProvider( new BouncyCastleProvider());
if(arg.length < 2 || arg.length > 4){
System.out.println("Usage:-c|-e|-d psd [inputFile] [outputFile]");
System.exit(1);
}
if("-c".equals(arg[0])){
generateKey(psd);
}
else if ("-e".equals(arg[0])){
encryt(psd, arg[2], arg[3]);
}
else if("-d".equals(arg[0])){
decryt(psd,arg[2], arg[3]);
}
else{
System.out.println("Usage:-c|-e|-d psd [inputFile] [outputFile]");
}
}
/*采用ASE加密算法产生密钥,create a 256-bit Rijndael key and stores it to
* the filesystem as a KeyStore
*/
private void generateKey(char psd[]) throws Exception{
KeyGenerator keyGenerator =KeyGenerator.getInstance("Rijndael");
keyGenerator.init(256);//java.security.InvalidParameterException: Wrong
keysize: must be equal to 128, 192 or 256
Key key = keyGenerator.generateKey();
byte [] salt =new byte[8];
SecureRandom random= new SecureRandom();
random.nextBytes(salt);
PBEKeySpec pbeKeySpec = new PBEKeySpec(psd);
SecretKeyFactory keyFortory = SecretKeyFactory.getInstance
("PBEWithSHAAndTwofish-CBC");
SecretKey pbeKey=keyFortory.generateSecret(pbeKeySpec);
PBEParameterSpec pbeParaSpec= new PBEParameterSpec(salt, iteration);
Cipher cipher = Cipher.getInstance("PBEWithSHAAndTwofish-CBC");
cipher .init(Cipher.ENCRYPT_MODE, pbeKey, pbeParaSpec);??????????
??
byte [] encryptedKeyBytes = cipher.doFinal(key.getEncoded());
File keyFileName = new File(Key_Filename);
if(!keyFileName.exists()){
keyFileName.createNewFile();
}
FileOutputStream fos = new FileOutputStream(keyFileName);
fos.write(salt);
fos.write(encryptedKeyBytes);
fos.flush();
fos.close();
}
//从文件系统中加载key.使用口令解密后返回密钥明文
private Key loadKey(char psd[]) throws Exception{
FileInputStream in = new FileInputStream(Key_Filename);
ByteArrayOutputStream baos =new ByteArrayOutputStream();
int i=0;
while((i=in.read())!=-1){
baos.write(i);
}
in.close();
byte[] saltAndKeyBytes =baos.toByteArray();
baos.close();
byte [] salt = new byte[8];
System.arraycopy(saltAndKeyBytes, 0, salt, 0, 8);
int keyByteLength = saltAndKeyBytes.length-8;
byte [] encrytedKeyBytes = new byte[keyByteLength];
System.arraycopy(saltAndKeyBytes, 8, encrytedKeyBytes, 0,
encrytedKeyBytes.length);
PBEKeySpec pbeKeySpec = new PBEKeySpec(psd);
SecretKeyFactory keyFortory = SecretKeyFactory.getInstance
("PBEWithSHAAndTwofish-CBC");
SecretKey pbeKey=keyFortory.generateSecret(pbeKeySpec);
PBEParameterSpec pbeParaSpec= new PBEParameterSpec(salt, iteration);
Cipher cipher = Cipher.getInstance("PBEWithSHAAndTwofish-CBC");
cipher .init(Cipher.DECRYPT_MODE, pbeKey, pbeParaSpec);
byte decrytedKeyBytes[]=cipher.doFinal(encrytedKeyBytes);
SecretKeySpec key = new SecretKeySpec(decrytedKeyBytes, "Rijndael");
return key;//向上转型
}
private void encryt(char psd[],String FileInput,String FileOutput)throws Exception{
Key key=loadKey(psd);
Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS5Padding");
SecureRandom random= new SecureRandom();//安全随机数会花一点时间
byte [] iv =new byte[16];
random.nextBytes(iv);
IvParameterSpec ivSpec= new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key,ivSpec);
FileInputStream in = new FileInputStream(FileInput);
FileOutputStream out = new FileOutputStream(FileOutput);
out.write(iv);//把iv作为最开始的16个字节写在文件中
CipherOutputStream cops = new CipherOutputStream(out, cipher);
int encrytWriteByte = 0;
while((encrytWriteByte =in.read())!=-1){
cops.write(encrytWriteByte);
}
in.close();
out.close();
cops.flush();
cops.close();
}
private void decryt(char psd[],String FileInput,String FileOutput)throws Exception{
Key key=loadKey(psd);
Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS5-Padding");
FileInputStream in = new FileInputStream(FileInput);
FileOutputStream out = new FileOutputStream(FileOutput);
byte [] iv =new byte[16];
in.read(iv);//把字节数组分配的内存读满后不产生异常
IvParameterSpec ivSpec= new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key,ivSpec);
CipherInputStream cips = new CipherInputStream(in, cipher);
int decryteWriteByte = 0;
while((decryteWriteByte= cips.read())!=-1){
out.write(decryteWriteByte);
}
in.close();
out.close();
cips.close();
}
}
调用FileEncrytor.java
/*问题1:为什么密钥的长度不能超过7
*
*问题2:为什么密要长度时256bit时,无法对文件进行对称加密
*
*问题3:当把Rijndael/CBC/PKCS5Padding换成RC4流加密解密算法时
*密钥生成使用DESede算法,提示:
*java.security.InvalidKeyException: Not an ARCFOUR key: DESede
*/
import java.io.File;
public class ExecFileEncrytor {
public static void main(String[] args) {
String psd = "12345678";
String inputFile = "D:"+File.separator+"inputFile.txt" ;
String outputFile = "D:"+File.separator+"outputFile.txt";
String arg[]={"-c",psd,inputFile,outputFile};
FileEncrytor fileE = new FileEncrytor();
try {
fileE.ManageCipherStream(arg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
- Rijndacel基于口令的对称加密
- java 对称加密——基于口令的加密与解密
- 基于Base64的对称加密
- 提供一个基于.NET的加密/解密算法(对称加密)
- 基于AES对称加密解密的代码块
- 9.9.2 加密的口令
- SSL/TLS 协议详解【基于key的对称加密和不对称加密、不基于key的】
- 口令加密
- 对称加密的对称密钥分发
- 带有口令加密的注册页面
- Java安全编程:基于口令加密(PBE)
- 使用的DES对称加密
- 使用的DES对称加密
- 对称加密技术的优缺点
- .NET对称加密的例子
- 对称加密的密钥交换
- CryptAPI对称加密的例子
- 对称加密和非对称加密的比较
- linux ls -l 命令 详解
- Transform – iOS视图几何变换
- linux常用命令(一)
- oracle存储过程的递归调用
- 学习VI编辑器
- Rijndacel基于口令的对称加密
- Objective-C对象的申请空间与初始化
- django datetime
- Android中文API最新中文版
- js实现页面跳转
- 估计google封闭Google Sync效劳
- poj 2388 Who's in the Middle
- Love2D学习 - 代码2
- C++ STL map 删除元素的问题