`

PKI体系简易JAVA实现(二):AES对称加密

阅读更多

PKI体系中关键的一环是消息体本身的加密传输。消息的加密可以采用非对称加密和对称加密。

 

1.概念:

对称密钥加密:又叫专用密钥加密,即发送和接收数据的双方必使用相同的密钥对明文进行加密和解密运算。简单的说,就是同一个密钥即可以加密也可以用来解密。常见的算法如DES,AES

 

非对称密钥加密:采用双钥密码系统的加密方法,在一个过程中使用两个密钥,一个用于加密,另一个用于解密,这种加密方法称为非对称加密,也称为公钥加密,因为其中一个密钥是公开的(另一个则需要保密)。常见算法如RSA

 

对称加密        速度快,安全性较低

非对称加密     速度较慢,安全性较高

 

2.为什么用对称加密消息正文

那假设我们要对QQ消息进行加密,采用非对称加密太耗费性能,速度又比较慢,而直接只用对称加密又显得没达到严格加密的要求。因此现行通常的做法是:

 

QQ聊天内容采用对称密钥,这样速度快,而在正式开始之前先用非对称密钥加密 对称密钥

 

这样相当于先建立了一个比较安全的可信通道,然后在这个通道里用比较快的加密方法通讯。

 

3.JAVA实现:

因此我们这里先关注消息正文的对称加密的实现。我们这里采用AES进行对称加密。

 

我们设计一个实现类叫做AESImpl, 理所当然,这个类最基本的就是提供加密和解密的功能。但是现实的情况可能会复杂一些。我们可能是传输一段文字(String),也有可能是发送一个文件(File), 而对于加密,我们可能需要自己设定密码,也可能是要程序自动生成一个密钥文件用于加解密。 

 

不过无论是什么需要,AES加解密JAVA实现的根本是一致的。都是通过javax.crypto.Cipher对象。甚至是加密解密这两种逆过程,都仅仅是cipher.init方法传入参数选Cipher.ENCRYPT_MODE还是Cipher.DECRYPT_MODE罢了。因此我们可以抽出一个"根AES加解密方法",用于持有加解密的公共逻辑,并且用于应对不同的加解密场景。

 

其他话就不多说了,具体看代码最清楚了:

 

import java.io.*;
import java.security.*;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;


/**
 * AES加解密工具实现(支持对字符串或文件加解密,支持生成密钥或使用密码)
 * @author nneverwei
 * @e-mail: nneverwei@gmail.com
 *
 */
public class AESImpl {
	
	/**
	 * 生成AES密钥
	 * @return AES密钥
	 */
	public static SecretKey createKey() {
		try {
			KeyGenerator keygen = KeyGenerator.getInstance("AES");
			SecureRandom random = new SecureRandom("nneverwei".getBytes());
			keygen.init(random);
			SecretKey key = keygen.generateKey();
			return key;
		} catch (NoSuchAlgorithmException e) {
			System.out.println("AES生成密钥错误");
			e.printStackTrace();
			return null;
		}
	}
	
    /**
     * 加密Str(使用密码)
     * @param content 需要加密的内容
     * @param password  加密密码
     * @return
     */
    public static byte[] encrypt(String content, String password) {
    	return (byte[]) rootCrypt(Cipher.ENCRYPT_MODE, content.getBytes(), password);
    }
    
    /**
     * 加密Str(使用密钥)
     * @param content 需要加密的内容
     * @param key  加密密钥
     * @return
     */
    public static byte[] encrypt(String content, Key key) {
    	return (byte[]) rootCrypt(Cipher.ENCRYPT_MODE, content.getBytes(), key);
    }
    
    /**
     * 解密Str(使用密码)
     * @param content  待解密内容
     * @param password 解密密码
     * @return
     */
    public static byte[] decrypt(byte[] content, String password) {
    	return (byte[]) rootCrypt(Cipher.DECRYPT_MODE, content, password);
    }
    
    /**
     * 解密Str(使用密钥)
     * @param content  待解密内容
     * @param key 解密密钥
     * @return
     */
    public static byte[] decrypt(byte[] content, Key key) {
    	return (byte[]) rootCrypt(Cipher.DECRYPT_MODE, content, key);
    }
    
    /**
     * 加密File(使用密码)
     * @param content 需要加密的内容
     * @param password  加密密码
     * @return
     */
    public static File encrypt(File content, String password) {
    	return (File) rootCrypt(Cipher.ENCRYPT_MODE, content, password);
    }
    
    /**
     * 加密File(使用密钥)
     * @param content 需要加密的内容
     * @param key  加密密钥
     * @return
     */
    public static File encrypt(File content, Key key) {
    	return (File) rootCrypt(Cipher.ENCRYPT_MODE, content, key);
    }
    
    /**
     * 解密File(使用密码)
     * @param content  待解密内容
     * @param password 解密密码
     * @return
     */
    public static File decrypt(File content, String password) {
    	return (File) rootCrypt(Cipher.DECRYPT_MODE, content, password);
    }
    
    /**
     * 解密Str(使用密钥)
     * @param content  待解密内容
     * @param key 解密密钥
     * @return
     */
    public static File decrypt(File content, Key key) {
    	return (File) rootCrypt(Cipher.DECRYPT_MODE, content, key);
    }
    
    /**
     * 加解密根方法
     * @param mode Cipher.ENCRYPT_MODE或Cipher.DECRYPT_MODE
     * @param msg 欲加密\解密消息体(支持String或File)
     * @param key 密码或密钥(支持String或Key)
     * @return byte[]或File
     */
    private static Object rootCrypt(int mode, Object msg, Object key){
    	try{
	    	Key passKey = null;
	    	if(key instanceof String){
	    		KeyGenerator kgen = KeyGenerator.getInstance("AES");
				kgen.init(128, new SecureRandom(((String) key).getBytes()));
				SecretKey secretKey = kgen.generateKey();
				byte[] enCodeFormat = secretKey.getEncoded();
				passKey = new SecretKeySpec(enCodeFormat, "AES");
	    	}else{
	    		passKey = (Key) key;
	    	}
	    	Cipher cipher = Cipher.getInstance("AES");// 创建密码器
            cipher.init(mode, passKey);// 初始化
            if(msg instanceof byte[]){
            	return cipher.doFinal((byte[]) msg);
            }else{
            	File file = (File)msg;
            	String fileName = file.getName();
            	String prefix=fileName.substring(fileName.lastIndexOf(".")+1);
            	File encryptFile = new File((mode == Cipher.ENCRYPT_MODE?"encrypt.":"decrypt.") + prefix);
    			InputStream in = new FileInputStream(file);
    			OutputStream out = new FileOutputStream(encryptFile);
                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) {
        			inLength = in.read(inBytes);
        			if (inLength == blockSize) {
        				int outLength = cipher.update(inBytes, 0, blockSize, outBytes);
        				out.write(outBytes, 0, outLength);
        			} else
        				more = false;
        		}
        		if (inLength > 0) {
        			outBytes = cipher.doFinal(inBytes, 0, inLength);
        		} else {
        			outBytes = cipher.doFinal();
        		}
        		out.write(outBytes);
        		in.close();
        		out.close();
                return encryptFile;
            }
    	}catch(Exception e){
    		e.printStackTrace();
    		return null;
    	}
    }
    
	public static void main(String[] args) {
		byte[] afterEncrypt = AESImpl.encrypt("你好啊哈哈哈哈哈", "weichao");
		System.out.println("加密后:" + new String(afterEncrypt));
		byte[] afterDecrypt = AESImpl.decrypt(afterEncrypt, "weichao");
		System.out.println("解密后:" + new String(afterDecrypt));
		
		SecretKey key = AESImpl.createKey();
		byte[] afterEncrypt2 = AESImpl.encrypt("sfasfasf水电费哈利开始发", key);
		System.out.println("加密后:" + new String(afterEncrypt2));
		byte[] afterDecrypt2 = AESImpl.decrypt(afterEncrypt2, key);
		System.out.println("解密后:" + new String(afterDecrypt2));
		
		File file = new File("hello.txt");
		File outFile = AESImpl.encrypt(file, key);
		File outFile2 = AESImpl.decrypt(outFile, key);
	}

}

 

 

0
2
分享到:
评论

相关推荐

    加密算法PKI

    包括: 密码学基础 2PKI体系 3PKI应用 详细讲解了通讯双方掌握的秘钥 包括典型算法:DES,3DES,AES,IDEA

    密码编码学与网络安全:原理与实践[第二部分:共两部分]

    第四版与第三版相比,新增了Whirlpool,CMAC,DDoS以及CCITSE等内容,并对简化的AES,PKI等内容做了扩充。此外,对于基本内容的讲述方法也有许多变化和更新,并新加了100多道习题。 本书可作为信息类专业高年级本科...

    openssl-1.0.0a

     OpenSSL一共实现了4种非对称加密算法,包括DH算法、RSA算法、DSA算法和椭圆曲线算法(EC)。DH算法一般用户密钥交换。RSA算法既可以用于密钥交换,也可以用于数字签名,当然,如果你能够忍受其缓慢的速度,那么也...

    SSL网络安全技术白皮书.docx

    协议安全机制 SSL协议实现的安全机制包括: 数据传输的机密性:利用对称密钥算法对传输的数据进行加密。 身份验证机制:基于证书利用数字签名方法对服务器和客户端进行身份验证,其中客户端的身份验证是可选的。 ...

    OpenSSL-1_0_0d_Win32

    非对称加密算法 OpenSSL一共实现了4种非对称加密算法,包括DH算法、RSA算法、DSA算法和椭圆曲线算法(EC)。DH算法一般用户密钥交换。RSA算法既可以用于密钥交换,也可以用于数字签名,当然,如果你能够忍受其缓慢的...

    上海复旦微电子FM15160安全芯片产品说明书

    支持 SM1、SM7、SSF33、SMS4、DES/3DES、AES 等对称算法,支持 SM2、ECC、RSA 等非对称算法,支持 SM3、SHA1、SHA256、MD5 等杂凑算法; 内置硬件真随机数发生器和安全防护电路;具有多用户程序隔离和保护能力。FM...

    密码编码学与网络安全:原理与实践[第一部分:共两部分]

    第四版与第三版相比,新增了Whirlpool,CMAC,DDoS以及CCITSE等内容,并对简化的AES,PKI等内容做了扩充。此外,对于基本内容的讲述方法也有许多变化和更新,并新加了100多道习题。 本书可作为信息类专业高年级本科...

    物联网安全_实验9 信息保密性、完整性和不可抵赖性的综合应用.doc

    (2)加密:PGP产生一个会话密钥,并加密消息;PGP用接收者UserID从公钥环中获取其公钥;构造消息的会话密钥部分。 PGP接收方处理消息的过程为:(1)解密消息:PGP用消息的会话密钥部分中的KeyID作为索引,从私钥...

    matasano:Matasano(现为NCC Group)加密货币挑战解决方案

    这些练习源于现实系统中的弱点和现代加密结构,这些结构涵盖了对称密码(例如AES)(在各种模式下),填充方案(例如PKCS#7),随机数生成器,哈希算法,非对称密码(例如)等主题。 DSA和RSA,各种著名的攻击等等...

    Simple file encryption utility-开源

    CRY实用程序提供了对文件执行AES-256对称密钥加密的功能。 这是一个轻量级Linux实用程序,并且不依赖于PKI基础结构。 而是,预共享的加密密钥用于保护您的文件。

Global site tag (gtag.js) - Google Analytics