码迷,mamicode.com
首页 > 编程语言 > 详细

对称加密详解,以及JAVA简单实现

时间:2017-07-21 13:28:37      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:个数   ges   world   i++   hello   ascii码   ret   一个   package   

 

(原)

常用的加密有3种

1、正向加密,如MD5,加密后密文固定,目前还没办法破解,但是可以能过数据库撞库有一定概率找到,不过现在一般用这种方式加密都会加上盐值。

2、对称加密,通过一个固定的对称密钥,对需要传输的数据进行加解密,速度快,但是安全性不高,主要用于企业级内部系统中数据传输。

3、非对称加密,N把公钥,一把私钥,私钥存放在服务器一方保管,公钥放可以放在任何一个客户端,客户端向服务器请求的密文只有拿到了私钥的服务器一端可以解密。

这里有个概念解释一下,

随机盐值(solt):

abcd  ->  MD5加密 ->  E2FC714C4727EE9395F324CD2E7F331F

然后通过撞库的方式,这种简单的字符一般都能很快的被找到

技术分享

如果我定义一个只有自己知道的字符串,放在要加密的文的任何地方,比如我在abcd第二个字符前加上:helloword123123,那么要加密的字符就变成了:ahelloword123123world。

我们对这个再次进行加密:

ahelloword123123world  ->  MD5加密 ->  978E1014EEFF5E0A708314DB2E7D6DA1

我们再次通过撞库的方式来解密:

技术分享

发现这次再通过撞库的方式解密失败了。这里的盐值的作用相当于扰乱了正常要加密的字符,而这个规律只有开发者,服务端的人知道。

^(异或)运算的作用。

它的运算规则是二进制运算中,相同得0,不同得1,如:2的二进制是10,3的二进制是11,最后得到的结果是01,转成十进制就是1。

如图:

技术分享

异或运算还有一个特殊的性质,就是逆运算,就拿刚才的例子来说,2^3=1,无论2、3、1中哪二个数做异或,结果永远只会等于另一个数。

比如:

2^3=1

2^1=3

3^1=2,通过异或这种特殊的运算性质,用它来做对称加密是比较好的选择。

下面给一个JAVA的简单实现:

 将1234用密钥abc加密。

思路:

1、先将1234转换成二进制,即ASCII码。

技术分享

加密:

1、2、3、4分别对应着49、50、51、52

49 -> 加密过程为:49 ^ 密钥 ^ 盐值  -> m1

50 -> 加密过程为:50 ^ 密钥 ^ m1  -> m2

51 -> 加密过程为:51 ^ 密钥 ^ m2  -> m3

52 -> 加密过程为:52 ^ 密钥 ^ m3  -> m4

经过上述运算后,密文就变成了m1、m2、m3、m4。

解密:

解密是上面加密的逆运算:已知条件为m1、m2、m3、m4

m4 -> 解密过程为:m4 ^ m3 ^  密钥 -> 52

m3 -> 解密过程为:m3^ m2 ^  密钥 -> 51

m2 -> 解密过程为:m2 ^ m1 ^  密钥 -> 50

m1 -> 解密过程为:m1 ^ 盐值 ^  密钥 -> 49

下面给出JAVA实现代码:

package com.lee;

public class Encryption {
    public static void main(String[] args)  {
        String content = "1234"; //需要加密的字符
        String key = "abc"; //密钥

        byte[] result = encryption(content, key);

        System.out.println("1234加密后的值:" + new String(result));
        System.out.println("---------------");
        System.out.println("1234解密后的值:" +new String(decipher(new String(result), key)));
    }


    public static byte[] encryption(String content,String key){
        byte[] contentBytes = content.getBytes();
        byte[] keyBytes = key.getBytes();

        byte dkey = 0;
        for(byte b : keyBytes){
            dkey ^= b;
        }

        byte salt = 0;  //随机盐值
        byte[] result = new byte[contentBytes.length];
        for(int i = 0 ; i < contentBytes.length; i++){
            salt = (byte)(contentBytes[i] ^ dkey ^ salt);
            result[i] = salt;
        }
        return result;
    }

    public static byte[] decipher(String content,String key){
        byte[] contentBytes = content.getBytes();
        byte[] keyBytes = key.getBytes();

        byte dkey = 0;
        for(byte b : keyBytes){
            dkey ^= b;
    }

        byte salt = 0;  //随机盐值
        byte[] result = new byte[contentBytes.length];
        for(int i = contentBytes.length - 1 ; i >= 0 ; i--){
            if(i == 0){
                salt = 0;
            }else{
                salt = contentBytes[i - 1];
            }
            result[i] = (byte)(contentBytes[i] ^ dkey ^ salt);
        }
        return result;
    }
}

输出结果为:

技术分享

 

对称加密详解,以及JAVA简单实现

标签:个数   ges   world   i++   hello   ascii码   ret   一个   package   

原文地址:http://www.cnblogs.com/LeeScofiled/p/7217065.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!