java安全——加密
来源:互联网 发布:美国eia原油库存数据公布时间 编辑:程序博客网 时间:2024/06/06 03:29
Cipher cipher = Cipher.getInstance(algorithName);
1.2)获取密码对象:或者调用下面这个方法:
Cipher cipher = Cipher.getInstance(algorithName, providerName);
2)SunJCE:JDK中是由名为"SunJCE"的提供商提供密码,如果没有指定其他提供商,则会默认该提供商。
int mode = . . .;Key key = . . .;cipher.init(mode, key);Attention)
Cipher.ENCRYPT_MODECipher.DECRYPT_MODECipher.WRAP_MODECipher.UNWRAP_MODEA2)wrap 和 unwrap模式用一个密钥对另一个密钥进行加密;
step3) 完成上述操作后,还必须调用一次doFinal方法。
step3.1)如果有最后一个输入数据块(其字节数小于blockSize),那么就要调用:
outBytes = cipher.doFinal(inBytes, 0, inLength);
step3.2)如果所有的输入数据都已经加密,则用下面的方法调用来代替:
outBytes = cipher.doFinal();Attention)对doFinal的调用是必要的,以便对最后的块进行"填充"。
step2) 用随机源来初始化密钥发生器。如果密码块的长度是可变的,还需要指定期望的密码块长度。
step3) 调用generateKey方法。
2)看个荔枝:下面是如何生成AES密钥的方法
keyGenerator keygen = KeyGenerator.getInstance("AES");SecureRandom random = new SecureRandom();keygen.init(random);Key key = keygen.generateKey();2.1)或者,可以从一组固定的原始数据(也许是由口令或者随机击键产生的)来生成一个密钥,这时可以使用如下的SecretKeyFactory:(干货——引入SecretKeyFactory)
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("AES");
byte[] keyData = . . .; // 16 bytes for AESSecretKeySpec keySpec = new SecretKeySpec(keyData, "AES");Key key = keyFactory.generateSecret(keySpec);
3)problem+solution:
3.1)problem: 如果要生成密钥,必须使用"真正的随机"数。例如,在Random类中的常规的随机数发生器,是根据当前的日期和时间来产生随机数的,因此它不够随机。例如,假设计算机时钟可以精确到1/10秒,那么,每天最多存在864,000个种子。如果攻击者知道发布密钥的日期(通常可以由截止日期推算出来),那么就可以很容易地生成那一天所有可能的种子。
3.2)solution: SecureRandom类产生的随机数,远比由Random类产生的那些数字安全得多。一旦你在字节数组中收集到随机位后,就可以将它传递给setSeed方法。(干货-SecureRandom类产生的随机数,远比由Random类产生的那些数字安全得多。)
SecureRandom secrand = new SecureRandom();byte[] b = new byte[20];// fill with truly random bitssecrand.setSeed(b);Attention) 如果没有为随机数发生器提供种子,那么它将通过启动线程,使它们睡眠,然后测量它们被唤醒的准确时间,来计算自己的20个字节的种子。
package com.corejava.chapter9.cryption;import java.io.*;import java.security.*;import javax.crypto.*;public class AESTest{ public static void main(String[] args) throws IOException, GeneralSecurityException, ClassNotFoundException { if (args[0].equals("-genkey")) // 产生密钥 { // 获取密钥生成器 KeyGenerator keygen = KeyGenerator.getInstance("AES"); // 创建随机源 SecureRandom random = new SecureRandom(); // 用随机源来初始化密钥发生器 keygen.init(random); // 生成密钥 SecretKey key = keygen.generateKey(); try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(args[1]))) { out.writeObject(key); // 写出密钥到文件 } } else // 加密或者解密 { int mode; // 加密(解密)模式 if (args[0].equals("-encrypt")) mode = Cipher.ENCRYPT_MODE; else mode = Cipher.DECRYPT_MODE; // 带资源的try 语句, args[3]==secret.key try (ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(args[3])); InputStream in = new FileInputStream(args[1]); OutputStream out = new FileOutputStream(args[2])) { Key key = (Key) keyIn.readObject(); Cipher cipher = Cipher.getInstance("AES"); cipher.init(mode, key); // 设置模式和密钥对其初始化 Util.crypt(in, out, cipher); } } }}
package com.corejava.chapter9.cryption;import java.io.*;import java.security.*;import javax.crypto.*;public class Util{ public static void crypt(InputStream in, OutputStream out, Cipher cipher) throws IOException, GeneralSecurityException { int blockSize = cipher.getBlockSize(); int outputSize = cipher.getOutputSize(blockSize); byte[] inBytes = new byte[blockSize]; byte[] outBytes = new byte[outputSize]; int inLength = 0; boolean more = true; while (more) { // inBytes 就是一个缓冲区 inLength = in.read(inBytes); if (inLength == blockSize) { // 只要输入数据块具有全长度(长度能够被8整除): 就要调用update方法; int outLength = cipher.update(inBytes, 0, blockSize, outBytes); out.write(outBytes, 0, outLength); } else more = false; } // 而如果输入数据块不具有全长度(长度不能被8整除,此时需要填充): 就要调用 doFinal 方法; if (inLength > 0) outBytes = cipher.doFinal(inBytes, 0, inLength); else outBytes = cipher.doFinal(); out.write(outBytes); }}
5.1)请按照如下 steps 使用上述程序:
step1)首先生成一个密钥,运行如下命令行:
java AESTest -genkey secret.key
step2)密钥就被保存在secret.key文件中了。现在可以用如下命令进行加密:
java AESTest -encrypt plaintextFile encryptedFile secret.key
step3)用如下命令进行解密:
java AESTest -decrypt encryptedFile decryptedFile secret.key
E:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>javac com/corejava/chapter9/cryption/AESTest.javaE:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.AESTest -genkey com/corejava/chapter9/cryption/secret.keyE:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.AESTest -encrypt com/corejava/chapter9/cryption/input.txt com/corejava/chapter9/cryption/output.txt com/corejava/chapter9/cryption/secret.keyE:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.AESTest -encrypt com/corejava/chapter9/cryption/input.txt com/corejava/chapter9/cryption/encrypted.txt com/corejava/chapter9/cryption/secret.keyE:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.AESTest -decrypt com/corejava/chapter9/cryption/encrypted.txt com/corejava/chapter9/cryption/decrypted.txt com/corejava/chapter9/cryption/secret.key
Cipher cipher = . . .;cipher.init(Cipher.ENCRYPT_MODE, key);CipherOutputStream out = new CipherOutputStream(new FileOutputStream(outputFileName), cipher);byte[] bytes = new byte[BLOCKSIZE];int inLength = getData(bytes); // get data from data sourcewhile (inLength != -1){out.write(bytes, 0, inLength);inLength = getData(bytes); // get more data from data source}out.flush();2.2)可以使用CipherInputStream,对文件的数据进行读取和解密:
Cipher cipher = . . .;cipher.init(Cipher.DECRYPT_MODE, key);CipherInputStream in = new CipherInputStream(new FileInputStream(inputFileName), cipher);byte[] bytes = new byte[BLOCKSIZE];int inLength = in.read(bytes);while (inLength != -1){putData(bytes, inLength); // put data to destinationinLength = in.read(bytes);}Attention) 密码流类能够透明地进行update 和 doFinal方法的调用,所以非常方便。
s1) Alice生成一个随机对称加密密钥,她用该密钥对明文进行加密。(第一次加密:对明文加密)
s2) Alice用Bob的公共密钥给对称密钥进行加密。(第二次加密:对对称密钥加密)
s3)Alice将加密后的对称密钥和加密后的明文同时发送给Bob。
s4) Bob用他的私有密钥给对称密钥解密。
s5) Bob用解密后的对称密钥给信息解密。
4)最普通的公共密钥算法: 是Rivest, Shamir, 和 Adleman发明的RSA算法。
5)如何使用RSA算法?
step1)如果要使用RSA算法,需要一对公共/私有密钥。你可以按如下方法使用KeyPairGenerator来获得:
KeyPairGenerator pairgen = KeyPairGenerator.getInstance("RSA");SecureRandom random = new SecureRandom();pairgen.initialize(KEYSIZE, random);KeyPair keyPair = pairgen.generateKeyPair();Key publicKey = keyPair.getPublic();Key privateKey = keyPair.getPrivate();step2)程序有三个选项。-genkey选项用于产生一个密钥对,-encrypt选项用于生成AES密钥,并且用公共密钥对其进行包装。
Key key = . . .; // an AES keyKey publicKey = . . .; // a public RSA keyCipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.WRAP_MODE, publicKey);byte[] wrappedKey = cipher.wrap(key);
step2.1)然后它便生成一个包含下列内容的文件(files):
f1)包装过的密钥的长度;
f2)包装过的密钥字节;
f3)用AES密钥加密的明文;
Attention)-decrypt选项: 用于对这样的文件进行解密。
6)代码列表
package com.corejava.chapter9.cryption;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.OutputStream;import java.security.GeneralSecurityException;import java.security.Key;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.SecureRandom;import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;public class RSATest{private static final int KEYSIZE = 512;public static void main(String[] args) throws GeneralSecurityException, IOException, ClassNotFoundException {if(args[0].equals("-genkey")) // 生成密钥对(公钥+私钥){// 密钥对生成器KeyPairGenerator pairgen = KeyPairGenerator.getInstance("RSA");SecureRandom sr = new SecureRandom();pairgen.initialize(KEYSIZE, sr); // 密钥对生成器初始化KeyPair pair = pairgen.generateKeyPair(); // 生成密钥对(公钥+私钥)try(ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(args[1]))){out.writeObject(pair.getPublic()); // 写入公钥到文件}try(ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(args[2]))){out.writeObject(pair.getPrivate()); // 写入私钥到文件}}else if(args[0].equals("-encrypt")) // 加密模块{// 生成密钥KeyGenerator keygen = KeyGenerator.getInstance("AES");SecureRandom sr = new SecureRandom();keygen.init(sr);SecretKey key = keygen.generateKey();// wrap with RSA public key// args[3]==public.key,args[2]==encryptedFile,args[1]=inputFiletry(ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(args[3]));DataOutputStream dataOut = new DataOutputStream(new FileOutputStream(args[2]));InputStream in = new FileInputStream(args[1])){Key publicKey = (Key)keyIn.readObject();// 读入公钥Cipher cipher = Cipher.getInstance("RSA");// RSA密码对象cipher.init(Cipher.WRAP_MODE, publicKey); // 通过设置打包模式和公钥 来对RSA密码对象进行初始化byte[] wrappedKey = cipher.wrap(key);// 通过带有公钥的RSA算法对象给密钥加密dataOut.writeInt(wrappedKey.length); // 将加密后的密钥写入到输出流 dataOutdataOut.write(wrappedKey);cipher = Cipher.getInstance("AES"); // AES 密码对象cipher.init(Cipher.ENCRYPT_MODE, key); // 通过设置加密模式和密钥 来对 AES 密码对象进行初始化Util.crypt(in, dataOut, cipher); // 利用AES密码对象对inFile 进行加密并写入到输出流 dataOut} }else // 解密模块{//args[1]==encryptedFile,args[3]=private.key,args[2]=decryptedFile;try(DataInputStream dataIn = new DataInputStream(new FileInputStream(args[1]));ObjectInputStream keyIn = new ObjectInputStream(new FileInputStream(args[3]));OutputStream out = new FileOutputStream(args[2])){ int length = dataIn.readInt();byte[] wrappedKey = new byte[length];dataIn.read(wrappedKey, 0, length); // 读入加密后的文件(经过公钥加密后的密钥 和 经过密钥加密后的文件内容)// unwrap with RSA private keyKey privateKey = (Key)keyIn.readObject(); // 读入private.key 到 wrappedKeyCipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.UNWRAP_MODE, privateKey); // 通过设置解包模式和私钥 来对RSA密码对象进行初始化// 通过带有私钥的RSA算法对象给密钥解密Key key = cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);cipher = Cipher.getInstance("AES"); // AES 密码对象cipher.init(Cipher.DECRYPT_MODE, key); // 通过设置解密模式和密钥 来对 AES 密码对象进行初始化Util.crypt(dataIn, out, cipher); // 通过使用解密后的密钥 对 加密后的文件内容 进行解密并写入到输出流 out} }}}<strong></strong>
7)运行该程序的steps:
step1)首先生成RSA密钥:
java RSATest -genkey public.key private.key
step2)然后对一个文件进行加密:
java RSATest -encrypt plaintextFile encryptedFile public.key
step3)最后,对文件进行解密,并且检验解密后的文件是否与明文相匹配。
java RSATest -decrypt encryptedFile decryptedFile private.key
最后的执行结果:E:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.RSATest -genkey com/corejava/chapter9/cryption/public.key com/corejava/chapter9/cryption/private.keyE:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.RSATest -encrypt com/corejava/chapter9/cryption/rsa_input.txt com/corejava/chapter9/cryption/rsa_encrypted.txt com/corejava/chapter9/cryption/public.keyE:\bench-cluster\cloud-data-preprocess\CoreJavaAdvanced\src>java com.corejava.chapter9.cryption.RSATest -decrypt com/corejava/chapter9/cryption/rsa_encrypted.txt com/corejava/chapter9/cryption/rsa_decrypted.txt com/corejava/chapter9/cryption/private.key
Attention)但是我们没有涉及许多高级和专有的话题,比如有:
A1)提供了对Kerberos协议进行支持的"通用安全服务"的GSS-API(原则上同样支持其他安全信息交换协议)。
A2)对SASL的支持,SASL即简单认证和安全层,可以为LDAP和IMAP协议所使用。
A3)对SSL的支持,SSL即安全套接层。在HTTP上使用SSL对应用程序的编程人员是透明的,只需要直接使用以https开头的URL即可。
- java安全——加密
- java 安全 加密 小解
- java安全 加密解密!
- Java安全加密
- Java安全加密
- Java/JSP安全及加密
- java安全AES加密解密
- java安全之加密技术
- Java安全架构____RSA加密
- Java安全系列-RSA加密
- 信息安全——加密与密码安全(一0
- 信息安全——加密解密技术
- iOS安全——常用加密
- Android 安全——Java环境动态加载Jar之Jar包的加密和解密
- java加密与解密的艺术(一)——何谓数据安全?
- JAVA数据加密——MD5加密,SHA加密,BASE64解密,BASE64加密,HMAC加密
- Java 安全编程加密了解2
- Java 安全编程加密了解1
- 在Xml中加注释的方法
- Linux 网卡驱动学习(五)(收发包具体过程)
- Android中View的性命周期
- Android性能优化典范
- jQuery常用方法归纳总结
- java安全——加密
- USACO: Spinning Wheels
- 程序员自我提高的几点建议 很实诚
- 理解innodb的索引页结构,插入缓冲,自适应哈希索引
- 小白学算法3.1——低位优先字符串排序
- First_OpenGL_Project——手把手教你创建第一个安卓openGL2.0项目
- linux下实时查看tomcat运行日志
- 谁的中国移动?
- Android开发之View.setTag(Object tag)