加密算法总结

对称与非对称加密算法的区别。

对称加密算法

加密(encryption)与解密(decryption)用的是同样的密钥(secret key),这种加密方式加密速度非常快,适合经常发送数据的场合。缺点是密钥的传输比较麻烦。

非对称加密算法

非对称加密为数据的加密与解密提供了一个非常安全的方法,它使用了一对密钥,公钥(public key)和私钥(private key)。私钥只能由一方安全保管,不能外泄,而公钥则可以发给任何请求它的人。非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥。比如,你向银行请求公钥,银行将公钥发给你,你使用公钥对消息加密,那么只有私钥的持有人--银行才能对你的消息解密。与对称加密不同的是,银行不需要将私钥通过网络发送出去,因此安全性大大提高。

常见的非对称加密算法为RSA、ECC和EIGamal。

一、Hex编码与解码

Hex 全称是Intel HEX。Hex文件是由一行行符合Intel HEX文件格式的文本所构成的ASCII文本文件。在Intel HEX文件中,每一行包含一个HEX记录。这些记录由对应机器语言码和/或常量数据的十六进制编码数字组成。

如下:

99、105、224,7

编码之后的数据为:“6369e007”,是一个字符串。

pom依赖     

  commons-codec

  commons-codec

  1.10

编码与解码测试如下:

/**

  * Hex编码

*/

public static String encodeHex(byte[] input) {

    return Hex.encodeHexString(input);

}

/**

  * Hex解码

  */

public static byte[] decodeHex(String input) {

    try {

        return Hex.decodeHex(input.toCharArray());

    } catch (DataBindingException e) {

        throw new RuntimeException();

    } catch (DecoderException e) {

        throw new RuntimeException();

    }

}

二、Base64编码与解码

/**

  * Base64编码

  */

public static String encodeBase64(byte[] input) {

    return Base64.encodeBase64String(input);

}

/**

  * Base64编码, URL安全(将Base64中的URL非法字符'+'和'/'转为'-'和'_', 见RFC3548)

  */

public static String encodeUrlSafeBase64(byte[] input) {

    return Base64.encodeBase64URLSafeString(input);

}

/**

  * Base64解码.

  */

public static byte[] decodeBase64(String input) {

    return Base64.decodeBase64(input);

}

测试如下:

public class Base64Test {

    public static void main(String[] args){

        String str = "Hello World";

        try{

            System.out.println("RESULT: " + encodeStr(str));

        } catch(UnsupportedEncodingException e){

            e.printStackTrace();

        }

    }

}

输出结果为:

1.  RESULT: SGVsbG8gV29ybGQ= 

上面输出的字符串是“Hello world”字符串的8位二进制值被连接在一起,然后以6位分组。随后每个组都被转换成一个单独的数字并映射到Base64的索引。

binary  dec Base64

010010  18  S

000110  6  G

010101  21  V

101100  44  s

011011  27  b

000110  6  G

111100  60  8

100000  32  g

010101  29  d

110110  54  2

111101  61  9

110010  50  y

011011  27  b

000110  6  G

010000  16  Q

注意:字符串最后加上了“=”,其意思表示字符串编码的结束。

三、URL编码与解码

当URL地址里包含非西欧字符的字符串时,浏览器都会将这些非西欧字符串转换成application/x-www-form-urlencoded MIME 字符串。在开发过程中,我们可能涉及将普通字符串和这种特殊字符串的相关转换,这就需要使用 URLDecoder 和 URLEncoder类进行实现,其中:

·      URLDecoder类包含一个decode(String s,String enc)静态方法,它可以将application/x-www-form-urlencoded MIME字符串转成普通字符串;

·      URLEncoder类包含一个encode(String s,String enc)静态方法,它可以将普通字符串转换成application/x-www-form-urlencoded MIME字符串。

普通字符串转与 application/x-www-form-urlencoded MIME 字符串之间的转化:

public class URLDecoderTest {

  public static void main(String[] args) throws Exception {

    // 将application/x-www-form-urlencoded字符串转换成普通字符串

    // 其中的字符串直接从上图所示窗口复制过来,chrome 默认用 UTF-8 字符集进行编码,所以也应该用对应的字符集解码

    System.out.println("采用UTF-8字符集进行解码:");

    String keyWord = URLDecoder.decode("%E5%A4%A9%E6%B4%A5%E5%A4%A7%E5%AD%A6+Rico", "UTF-8");

    System.out.println(keyWord);

    System.out.println("\n 采用GBK字符集进行解码:");

    System.out.println(URLDecoder.decode("%E5%A4%A9%E6%B4%A5%E5%A4%A7%E5%AD%A6+Rico", "GBK"));

    // 将普通字符串转换成application/x-www-form-urlencoded字符串

    System.out.println("\n 采用utf-8字符集:");

    String urlStr = URLEncoder.encode("天津大学", "utf-8");

    System.out.println(urlStr);

    System.out.println("\n 采用GBK字符集:");

    String urlStr2 = URLEncoder.encode("天津大学", "GBK");

    System.out.println(urlStr2);

  }

}

/*

Output:

采用UTF-8字符集进行解码:

天津大学 Rico

采用GBK字符集进行解码:

澶╂触澶у Rico

采用utf-8字符集:

%E5%A4%A9%E6%B4%A5%E5%A4%A7%E5%AD%A6

采用GBK字符集:

    %CC%EC%BD%F2%B4%F3%D1%A7

*/

四、AES加密或解密

高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法。对称加密算法也就是加密和解密用相同的密钥

密钥K:用来加密明文的密码,在对称加密算法中,加密与解密的密钥是相同的。密钥为接收方与发送方协商产生,但不可以直接在网络上传输,否则会导致密钥泄漏,通常是通过非对称加密算法加密密钥,然后再通过网络传输给对方,或者直接面对面商量密钥。密钥是绝对不可以泄漏的,否则会被攻击者还原密文,窃取机密数据。

1、密钥

就是把明文转换为密文,密文转换为明文的一把钥匙。接下来我们会用ASE加密技术生成一把密钥。

/**

* 生成AES密钥,可选长度为128,192,256位.

*/

public static byte[] generateAesKey(int keysize) {

  try {

    KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);

    keyGenerator.init(keysize);

    SecretKey secretKey = keyGenerator.generateKey();

    return secretKey.getEncoded();

  } catch (GeneralSecurityException e) {

    throw unchecked(e);

  }

}

2、加密,将明文和密钥一起,作为参数传入。

/**

* ASE 加密

* @param str 明文

* @param key 秘钥

* @return

*/

public static String enStr(String str, byte[] key) {

Cipher cipher = null;

SecretKey generateKey = null;

  try {

    generateKey = new SecretKeySpec(key, "AES");

    cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

    cipher.init(Cipher.ENCRYPT_MODE, generateKey);

    byte[] resultBytes = cipher.doFinal(str.getBytes());

    return Hex.encodeHexString(resultBytes);

  } catch (Exception e) {

    logger.error("AES加密出错", e);

  }

  return null;

}

3、解密,解密就是加密的互逆过程,所以代码很类似。

/**

* 解密

* @param key 秘钥

* @param str 密文

* @return

*/

public static String deStr(String str, byte[] key) {

  Cipher cipher = null;

  SecretKey generateKey = null;

  try {

  generateKey = new SecretKeySpec(key, "AES");

  cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

  cipher.init(Cipher.DECRYPT_MODE, generateKey);

  byte[] result = Hex.decodeHex(str.toCharArray());

  return new String(cipher.doFinal(result));

  } catch(Exception e) {

      logger.error("ASE解密出错", e);

  }

  return null;

}

通用公共抽取:

/**

* 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.

*

* @param input 原始字节数组

* @param key 符合AES要求的密钥

* @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE

*/

private static byte[] aes(byte[] input, byte[] key, int mode) {

    try {

        SecretKey secretKey = new SecretKeySpec(key, AES);

        Cipher cipher = Cipher.getInstance(AES);

        cipher.init(mode, secretKey);

        return cipher.doFinal(input);

    } catch (GeneralSecurityException e) {

        throw unchecked(e);

    }

}

五、DES加密与解密(3DES)

数据加密标准(DES Data Encryption Standard)

DES算法的入口参数有三个:Key、Data、Mode。

其中Key为8个字节共64位,是DES算法的工作密钥;

Data也为8个字节64位,是要被加密或被解密的数据;

Mode为DES的工作方式,有两种:加密或解密。

DES算法是这样工作的:

如Mode为加密,则用Key 去把数据Data进行加密,生成Data的密码形式(64位)作为DES的输出结果;

如Mode为解密,则用Key去把密码形式的数据Data解密,还原为Data的明码形式(64位)作为DES的输出结果。

3DES加密:

3DES是DES加密算法的一种模式,它使用3条64位的密钥对数据进行三次加密。数据加密标准(DES)是美国的一种由来已久的加密标准,它使用对称密钥加密法。

3DES(即Triple DES)是DES向AES过渡的加密算法(1999年,NIST将3-DES指定为过渡的加密标准),是DES的一个更安全的变形。它以DES为基本模块,通过组合分组方法设计出分组加密算法。

设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,P代表明文,C代表密表,这样,

3DES加密过程为:C=Ek3(Dk2(Ek1(P)))

3DES解密过程为:P=Dk1((EK2(Dk3(C)))

K1、K2、K3决定了算法的安全性,若三个密钥互不相同,本质上就相当于用一个长为168位的密钥进行加密。多年来,它在对付强力攻击时是比较安全的。若数据对安全性要求不那么高,K1可以等于K3。在这种情况下,密钥的有效长度为112位。

五、RSA加密与解密

非对称加密,公钥加密,私钥解密,反之亦然。由于需要大数的乘幂求模等算法,运行速度慢,不易于硬件实现。

通常私钥长度有512bit,1024bit,2048bit,4096bit,长度越长,越安全,但是生成密钥越慢,加解密也越耗时。

既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;

同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。

六、MD5加密(不可逆)

MD5即Message-Digest Algorithm 5(信息-摘要算法5), 非对称的加密算法

public static String MD5(String key) {

char hexDigits[] = {

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'

};

  try {

    byte[] btInput = key.getBytes();

    // 获得MD5摘要算法的 MessageDigest 对象

    MessageDigest mdInst = MessageDigest.getInstance("MD5");

    // 使用指定的字节更新摘要

    mdInst.update(btInput);

    // 获得密文

    byte[] md = mdInst.digest();

    // 把密文转换成十六进制的字符串形式

    int j = md.length;

    charstr[] = newchar[j * 2];

    int k = 0;

    for (int i = 0; i < j; i++) {

      byte byte0 = md[i];

      str[k++] = hexDigits[byte0 >>> 4 & 0xf];

      str[k++] = hexDigits[byte0 & 0xf];

    }

    return new String(str);

  } catch (Exception e) {

    returnnull;

  }

}

总结

哈希函数,比如MD5,SHA,这些都不是加密算法。要注意他们的区别和用途,很多网友都把md5说成是加密算法,这是严重不正确的啊。

哈希函数:MD5SHA 是没有密钥的,相当与指纹的概念,因此也是不可逆的;

md5128位的,SHA有不同的算法,有128256等位。。。如SHA-256,SHA-384

然后就是 Base64,这更加不属于加密算法的范围了,它只是将byte[]数组进行了转换,为什么要转换呢?就是因为很多加密后的密文后者一些特殊的byte[]数组需要显示出来,或者需要进行传递(电子邮件),但是直接转换就会导致很多不可显示的字符,会丢失一些信息,因此就转换位Base64编码,这些都是可显示的字符。所以转换后,长度会增加。它是可逆的。

再就是 3DES,DES 这才是加密算法,因此也是可逆的,加解密需要密钥,也就是你说的key

最后是 RSA ,这是公钥密码,也就是加密和解密密钥不同,也是可逆的。

你可能感兴趣的:(加密算法总结)