四种最常见的安全算法总结

     最近项目用到一些加密和安全算法,浏览了一些资料,

   总觉得缺少一篇让新手快速入门的基础而且比较全面的文章,

   这里把一些常用的安全算法和自己的总结发出来,有不对的地方请大家多多指教,

                                                                                          Orz~-~


    首先要了解用到的编码格式:


Base64编码,通过名字来看,也就是通过64个字符来表示信息的一种方法,并不要把它当做一种加密算法,因为任何人都可以通过Base64编码后的内容逆向得出编码之前的信息,这里可以简单的理解为通过Base64编码之后,将二进制信息编码成可打印的字符,便于在网络上传输,至于原理,想深入研究的,可以自行度娘。

用到的方法也就是 : 一个负责编码一个负责解码


Base64.encodeBase64String(byte[] b)
Base64.decodeBase64(String s)

这里引入  commons-codec-1.10.jar 这里只是其中的一种实现方式,原理都是相同的


十六进制编码:这里不需要再多说了,一般需要知道4位二进制数据对应一位16进制数据,十六进制是由0~9和A~F来表示,还有是不区分大小写的。
以上两种编码是比较常用的网络传输中使用到的编码。





接下来就列举出四种最常用的加密算法和实例:


第一种加密方法:消息摘要算法(摘要算法,哈希算法)


所谓的消息摘要算法,就是对一个消息或文本,产生一个固定长度的值(也就是摘要),采用的是单向的Hash函数对消息或文本进行计算产生,且不同的明文生成的摘要结果 "总是" 不同的,相同的明文产生的摘要 "必定" 一致。
这里目前最常用的摘要算法有 MD5 和 SHA1
       MD5是由MD4,MD3,MD2改进而来,摘要长度为128位,在目前应用比较广泛。
主要功能代码如下:

MessageDigest md5=MessageDigest.getInstance("MD5");
BASE64Encoder base64 = new BASE64Encoder();
String newstr=base64.encode(md5.digest(str.getBytes("utf-8")));  //这里一般转为Base64或者16进制输出

SHA有SHA1,SHA-224,SHA-256,SHA-384等,目前应用最广泛的也就是SHA1和SHA256这两个,SHA1输出的摘要长度是160位,而SHA-256输出的也就是256位,
从输出位数上就可以比较出安全性,SHA1比SHA256要低,但相比于MD5的128位,SHA家族是更安全的,但是位数长带来的也有负面的影响,MD5速度要比SHA家族更快,


主要功能代码如下:
MessageDigest md5=MessageDigest.getInstance("SHA-1");
BASE64Encoder base64 = new BASE64Encoder();
String newstr=base64.encode(md5.digest(str.getBytes("utf-8")));  //这里一般转为Base64或者16进制输出



第二种加密方法:对称加密算法(应用比较少)


        在对称加密算法中,数据发送方将原始数据和加密密钥一起经过特殊加密算法处理后,使其变成加密密文发送出去。
收信方收到密文后,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文。
在对称加密算法中,使用的密钥只有一个,发收信双方都使用这个密钥对数据进行加密和解密,这就要求解密方事先必须知道加密密钥。


优点在于:算法公开,计算量小,加密速度快,加密效率高,加解密的告诉和使用长密钥时的难破解性
缺点:安全性过于依赖密钥,泄露密钥就意味着任何人都可以加解密数据,因此对秘钥的保存至关重要



目前流行的主要有DES和AES:DES的密钥长64位,但事实上只有56位参与运算(8和8的倍数都为效验位),相对于DES,AES算法作为新一代的数据加密标准,汇聚了强安全性,高性能,高效率,易用和灵活的优点,包含(128,192,256)三种秘钥长度,比DES算法的加密强度更高,更为安全。


DES和AES的实现过程类似,主要都是包括两部分,主要代码如下:
生成密钥:
public static String genKeyDES() throws Exception{
		 KeyGenerator keyGen = KeyGenerator.getInstance("DES");   //或者AES
		 keyGen.init(56);                                         //128,192,256
		 SecretKey key = keyGen.generateKey();
		 BASE64Encoder base64 = new BASE64Encoder();
		 String base64Str = base64.encode(key.getEncoded());
		 return base64Str;
		 }


 这里为了方便存储,一般将得到的DES密钥Base64编码成字符串,
将相应的密钥字符串转换为SecretKey对象,只需要将密钥Base64解码后,传入对应算法实例化SecretKeySpec即可


 public static SecretKey loadKeyDES(String base64Key) throws Exception{
		 BASE64Decoder base64 = new BASE64Decoder();
		 byte[] bytes = base64.decodeBuffer(base64Key);
		 SecretKey key = new SecretKeySpec(bytes, "DES");       //或者AES
		 return key;
	 }


加密与解密:
//加密
	 public static byte[] encryptDES(byte[] suorce,SecretKey key) throws Exception{
		 Cipher cipher = Cipher.getInstance("DES");            
		 cipher.init(Cipher.ENCRYPT_MODE, key);	      
		 byte[] bytes = cipher.doFinal(source);
		 return bytes;
	 }


public static final int ENCRYPT_MODE    用于将 Cipher 初始化为加密模式的常量


public static final int DECRYPT_MODE    用于将 Cipher 初始化为解密模式的常量


还有其他字段,这里就不列举了,

加解密都需要实例化Cipher对象
Cipher类位于javax.crypto包下  public class Cipher extends Object  此类为加密和解密提供密码功能。
为创建 Cipher 对象,应用程序调用 Cipher 的 getInstance方法并将所请求转换 的名称传递给它。还可以指定提供者的名称(可选)。
转换 是一个字符串,它描述为产生某种输出而在给定的输入上执行的操作(或一组操作)。
转换始终包括加密算法的名称(例如,DES,AES),后面可能跟有一个反馈模式和填充方案。
转换具有以下形式:  “算法/模式/填充”或直接填写“算法”



第三种加密方法:非对称加密算法


      非对称加密算法又称为公开密钥加密算法,需要两个密钥:一个称为公开密钥即为公钥,另一个称为私有密钥即为私钥,公钥和私钥配对使用,公钥加密只有对应私钥可以解密,私钥加密,只有对应公钥可以解密。
因为传输数据的两方分别保存的分别为公钥和私钥,所以被称作非对称加密。


这里加密和签名是由区别的:需根据具体情况选择
加密:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;
同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证;


优点:包含两种密钥,其中一个公开的,一个保密,即使在获取到公钥,加密算法的情况下,也无法获取公钥对应的私钥,也无法对密文解密。
缺点:由于其复杂程度高,加解密速度远远没有对称加密解密的速度快。



目前使用最广泛的非对称加密算法:RSA
主要代码实现如下:


1,初始化秘钥对:
 /** 
     * 初始化密钥对 
     * @return Map 甲方密钥的Map 
     * */  
    public static Map<String,Object> initKey() throws Exception{  
        //实例化密钥生成器  
        KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("RSA");  
        //初始化密钥生成器  
        keyPairGenerator.initialize(512);  //密钥长度必须是64的倍数,在512到65536位之间 
        //生成密钥对  
        KeyPair keyPair=keyPairGenerator.generateKeyPair();  
        //甲方公钥  
        RSAPublicKey publicKey=(RSAPublicKey) keyPair.getPublic();  
        //甲方私钥  
        RSAPrivateKey privateKey=(RSAPrivateKey) keyPair.getPrivate();     
    }  


2,公钥和私钥解密:
/** 
     * 私钥解密 
     * @param data 待解密数据 
     * @param key 密钥 
     * @return byte[] 解密数据 
     * */  
    public static byte[] decryptByPrivateKey(byte[] data,byte[] key) throws Exception{  
        //取得私钥  
        PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(key);  
        KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);  
        //生成私钥  
        PrivateKey privateKey=keyFactory.generatePrivate(pkcs8KeySpec);  
        //数据解密  
        Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());  
        cipher.init(Cipher.DECRYPT_MODE, privateKey);  
        return cipher.doFinal(data);  
    }  
    /** 
     * 公钥解密 
     * @param data 待解密数据 
     * @param key 密钥 
     * @return byte[] 解密数据 
     * */  
    public static byte[] decryptByPublicKey(byte[] data,byte[] key) throws Exception{  
          
        //实例化密钥工厂  
        KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);  
        //初始化公钥  
        //密钥材料转换  
        X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);  
        //产生公钥  
        PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);  
        //数据解密  
        Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());  
        cipher.init(Cipher.DECRYPT_MODE, pubKey);  
        return cipher.doFinal(data);  
    }  



3:公钥和私钥加密:
 /** 
     * 私钥加密 
     * @param data待加密数据 
     * @param key 密钥 
     * @return byte[] 加密数据 
     * */  
    public static byte[] encryptByPrivateKey(byte[] data,byte[] key) throws Exception{  
          
        //取得私钥  
        PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(key);  
        KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);  
        //生成私钥  
        PrivateKey privateKey=keyFactory.generatePrivate(pkcs8KeySpec);  
        //数据加密  
        Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());  
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);  
        return cipher.doFinal(data);  
    }  
    /** 
     * 公钥加密 
     * @param data待加密数据 
     * @param key 密钥 
     * @return byte[] 加密数据 
     * */  
    public static byte[] encryptByPublicKey(byte[] data,byte[] key) throws Exception{  
          
        //实例化密钥工厂  
        KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM);  
        //初始化公钥  
        //密钥材料转换  
        X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);  
        //产生公钥  
        PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);  
          
        //数据加密  
        Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());  
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);  
        return cipher.doFinal(data);  
    }   



4:通过Base64编码的字符串加载公钥和私钥

	/**
	 * 得到公钥
	 * 
	 * @param key
	 *            密钥字符串(经过base64编码)
	 * @throws Exception
	 */
	public static PublicKey getPublicKey(String base64PublicKey) throws Exception {
		byte[] keyBytes = Base64.decode(base64PublicKey);
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PublicKey publicKey = keyFactory.generatePublic(keySpec);
		return publicKey;
	}

	/**
	 * 得到私钥
	 * 
	 * @param key
	 *            密钥字符串(经过base64编码)
	 * @throws Exception
	 */
	public static PrivateKey getPrivateKey(String base64PrivateKey) throws Exception {
		byte[] keyBytes = Base64.decode(base64PrivateKey);
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
		return privateKey;
	}







第四种加密方法:数字签名
数字签名是对非对称加密技术和摘要算法的综合运用,也就是将通信内容的摘要信息使用发送方的私钥进行加密,然后将密文与原文一起传输,接收方使用公钥解密被加密的摘要,然后使用相同的摘要算法,对接收到的信息采用相同的方式产生摘要,与解密的摘要进行对比,相同则验证通过,说明信息是完整的。
发送方:这里发送方可以简单说先使用SHA1(其它摘要算法)对数据提取摘要,再用私钥加密,发送的数据为原始数据和加密后的数据
接收方:而接收方简单的可以理解为用对应的公钥解密摘要数据(这里可以验证信息是由对应私钥拥有者发出的,保证了数据发送者的身份),再通过发送的原始数据进行摘要算法,把两份数据进行比较(这里验证了信息的完整性,保证没有被篡改过)


常用的数字签名方法有:MD5withRSA,SHA1withRSA,
这里可以简单的理解为前面两种算法的结合,主要算法如下:
java都已经封装,


摘要和私钥加密生成签名
/**
	 * RSA签名
	 * 
	 * @param content
	 *            待签名数据
	 * @param privateKey
	 *            私钥
	 * @param inputCharset
	 *            编码格式
	 * @return 签名值
	 */
	public static String genSign(String content, String privateKey, String inputCharset) {
		try {
			PrivateKey priKey = RSA.getPrivateKey(privateKey);
			java.security.Signature signature = java.security.Signature.getInstance("SHA1withRSA");
			signature.initSign(priKey);
			signature.update(content.getBytes(inputCharset));
			byte[] signed = signature.sign();
			return Base64.encodeBase64String(signed);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}


摘要和公钥验证签名
/**
	 * RSA验签名检查
	 * 
	 * @param content
	 *            待签名数据
	 * @param sign
	 *            签名值
	 * @param mchPublicKey
	 *            公钥
	 * @param inputCharset
	 *            编码格式
	 * @return 布尔值
	 */
	public static boolean verifySign(String content, String sign, String publicKey, String inputCharset) {
		try {
			PublicKey pubKey = RSA.getPublicKey(publicKey);
			java.security.Signature signature = java.security.Signature.getInstance("SHA1withRSA");
			signature.initVerify(pubKey);
			signature.update(content.getBytes(inputCharset));
			boolean bverify = signature.verify(Base64.decodeBase64(sign));
			return bverify;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}


以上只列举出了关键部分代码,都是测试过可以使用的,根据需要修改即可。














  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值