加密、解密、编码

urlencode

urlencode_百度百科

Base64是一种二进制到文本的编码方式,而且编码出的字符串只包含ASCII基础字符

下图是Base64码表,可以看到从0到63的每个数字都对应一个上面的一个字符。

GB2312

编码小于127的字符与ASCII编码相同,
特性:两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(称之为高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。

GBK

不再要求低字节一定是127号之后的内码,只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。结果扩展之后的编码方案被称为 “GBK” 标准

unicode

Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。

Unicode表示的字符的范围0x0000 - 0x10FFFF

Little endian 和 Big endian

以汉字为例,Unicode 码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候,4E在前,25在后,这就是 Big endian 方式;25在前,4E在后,这是 Little endian 方式。

第一个字节在前,就是"大头方式"(Big endian),第二个字节在前就是"小头方式"(Little endian)。

那么很自然的,就会出现一个问题:计算机怎么知道某一个文件到底采用哪一种方式编码?

Unicode 规范定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做"零宽度非换行空格"(zero width no-break space),用FEFF表示。这正好是两个字节,而且FFFE1

如果一个文本文件的头两个字节是FE FF,就表示该文件采用大头方式;如果头两个字节是FF FE,就表示该文件采用小头方式。

UTF-8

UTF-8 是 Unicode 的实现方式之一

UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

UTF-8 的编码规则很简单,只有二条:

1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。

2)对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。

下表总结了编码规则,字母x表示可用编码的位。

Unicode符号范围     |        UTF-8编码方式
(十六进制)        |              (二进制)
----------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

跟据上表,解读 UTF-8 编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。

下面,还是以汉字为例,演示如何实现 UTF-8 编码。

的 Unicode 是4E25100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800 - 0000 FFFF),因此的 UTF-8 编码需要三个字节,即格式是1110xxxx 10xxxxxx 10xxxxxx。然后,从的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,的 UTF-8 编码是11100100 10111000 10100101,转换成十六进制就是E4B8A5

UTF-8文件

unicode字符FE FF使用UTF-8编码后EF BB BF,所以UTF-8编码的文件很多以EF BB BF开头

utf-8不存在大头小头问题,Utf-8 bom表示文件头存在EF BB BF

java默认编码

java默认编码(一张图治愈多年强迫症)_java默认编码格式-CSDN博客

文件-base64字符串互转

sun.misc包中的类
try (FileOutputStream fos = new FileOutputStream(hdfsConfig.getTempDir() + fileName)) {
    BASE64Decoder decoder = new BASE64Decoder();
    byte[] b = decoder.decodeBuffer(baseStr);
    fos.write(b);
    fos.flush();
}
java.util包中的类
String content = "";
byte[] decode = Base64.getDecoder().decode(content);
FileUtils.writeByteArrayToFile(new File(localZipFilePath), decode);

md5

commons-codec.jar
import org.apache.commons.codec.digest.DigestUtils;

/** * MD5加密之方法一 * @explain 借助apache工具类DigestUtils实现 * @param str * 待加密字符串 * @return 16进制加密字符串 */
public static String encryptToMD5(String str) { 
   
	return DigestUtils.md5Hex(str);
}  

java.security.MessageDigest
/** * MD5加密之方法二 * @explain java实现 * @param str * 待加密字符串 * @return 16进制加密字符串 */
public static String encrypt2ToMD5(String str) { 
   
	// 加密后的16进制字符串
	String hexStr = "";
	try { 
   
		// 此 MessageDigest 类为应用程序提供信息摘要算法的功能
		MessageDigest md5 = MessageDigest.getInstance("MD5");
		// 转换为MD5码
		byte[] digest = md5.digest(str.getBytes("utf-8"));
		hexStr = ByteUtils.toHexString(digest);
	} catch (Exception e) { 
   
		e.printStackTrace();
	}
	return hexStr;
}  
spring核心包org.springframework.util.DigestUtils
/** * MD5加密之方法三 * @explain springboot自带MD5加密 * @param str * 待加密字符串 * @return 16进制加密字符串 */
 public static String encrypt3ToMD5(String str) { 
   
 	log.debug("MD5待加密字符串:\n"+str);
 	String md5 = " ";
 	try { 
   
 	md5 = DigestUtils.md5DigestAsHex(text.getBytes("utf-8"))
    } catch (UnsupportedEncodingException e) { 
   
    e.printStackTrace();
    }
    log.degbug("MD5加密结果:\n"+md5)
    return md5;
 }

SHA1

对称加密算法

DES

package org.cc.lipiao;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.Key;

public class EncritAndDecrit {

    private static String src = "imooc security des";

    public static void main(String[] args) {
        desDemo();
    }

    private static void desDemo(){
        try {
            //生成KEY
            KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
            keyGenerator.init(56);
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] bytesKey = secretKey.getEncoded();

            //KEY转换
            DESKeySpec desKeySpec = new DESKeySpec(bytesKey);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
            Key convertSecretKey = factory.generateSecret(desKeySpec);

            //加密
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
            byte[] result = cipher.doFinal(src.getBytes());

            //解密
            cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
            result = cipher.doFinal(result);
            System.out.println("jdk des decrypt : " + new String(result));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

AES

非对称加密算法

RSA

加密算法是目前最有影响力的 公钥加密算法,并且被普遍认为是目前 最优秀的公钥方案 之一。RSA 是第一个能同时用于 加密 和 数字签名 的算法,它能够 抵抗 到目前为止已知的 所有密码攻击,已被 ISO 推荐为公钥数据加密标准。

基于JDK RSA算法实现非对称加密解密

package org.cc.lipiao;

import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class EncritAndDecrit {

    private static final String RSA = "RSA";
    private static  byte[] privateKeyBytes ;
    private static  byte[] publicKeyBytes ;
    private static String src = "imooc security rsa";

    public static void main(String[] args) throws Exception {
        String s = publicKeyCrypto(src);
        privateKeyDecrypto(s);

        String s1 = privateKeyCrypto(src);
        publicKeyDecrypto(s1);
    }

    static {
        try {
            KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance(RSA);
            senderKeyPairGenerator.initialize(512);
            KeyPair keyPair = senderKeyPairGenerator.generateKeyPair();
            privateKeyBytes = keyPair.getPrivate().getEncoded();
            publicKeyBytes = keyPair.getPublic().getEncoded();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 公钥加密
     * @param originStr
     * originStr 需要加密的原始字符串
     * @return 经过公钥加密并base64编码的字符串
     */
    public static String publicKeyCrypto(String originStr) throws Exception{
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyBytes);
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        Cipher cipher = Cipher.getInstance(RSA);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] result = cipher.doFinal(originStr.getBytes());
        System.out.println("公钥加密后base64编码:" + Base64.encodeBase64String(result));
        return  Base64.encodeBase64String(result);
    }
    /**
     * 私钥解密
     * @param publicKeyCryptoStr
     * publicKeyCryptoStr 经过公钥加密并base64编码的字符串
     * @return 未加密的原始字符串
     */
    public static String privateKeyDecrypto(String publicKeyCryptoStr) throws Exception {
        byte [] originStrBytes = Base64.decodeBase64(publicKeyCryptoStr.getBytes());
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        Cipher cipher = Cipher.getInstance(RSA);
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] result = cipher.doFinal(originStrBytes);
        System.out.println("解密得到的字符串:" + new String(result));
        return new String(result);
    }

    /**
     * 私钥加密
     * @param originStr
     * originStr 需要加密的原始字符串
     * @return 经过私钥加密并base64编码的字符串
     */
    public static String privateKeyCrypto(String originStr) throws Exception {

        String resultStr = "";
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        Cipher cipher = Cipher.getInstance(RSA);
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        byte[] result = cipher.doFinal(originStr.getBytes());
        System.out.println("加密结果经过base64编码:" + Base64.encodeBase64String(result));
        resultStr =  Base64.encodeBase64String(result);
        return resultStr;
    }
    /**
     * 公钥解密
     * @param privateKeyCryptoStr
     * privateKeyCryptoStr 经过私钥加密后并base64编码的字符串
     * @return 未加密的原始字符串
     */
    public static String publicKeyDecrypto(String privateKeyCryptoStr) throws Exception {
        byte [] originStrBytes = Base64.decodeBase64(privateKeyCryptoStr.getBytes());
        String resultStr = "";
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        Cipher cipher = Cipher.getInstance(RSA);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyBytes);
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        byte[] result = cipher.doFinal(originStrBytes);
        System.out.println("公钥解密后:" + new String(result));
        resultStr = new String(result);
        return resultStr;
    }

}

DSA

BouncyCastle

相关参考链接:

国密算法介绍 - 知乎国密算法,即国家商用密码算法。是由国家密码管理局认定和公布的密码算法标准及其应用规范,其中部分密码算法已经成为国际标准。如SM系列密码,SM代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术…icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/132352160

浅谈常见的七种加密算法及实现 - 知乎前言 数字签名、信息加密 是前后端开发都经常需要使用到的技术,应用场景包括了用户登入、交易、信息通讯、oauth 等等,不同的应用场景也会需要使用到不同的签名加密算法,或者需要搭配不一样的 签名加密算法 来达…icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/347114235

api中文文档

API Reference Documenticon-default.png?t=N7T8https://www.apiref.com/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值