Java 中的加密使用和理解

我的网站 | 我的博客

常用加密

  • DES, Data Encryption Standard, 数据加密标准
  • 3DES, Triple DES, 三重数据加密算法
  • AES, Advanced Encryption Standard, 高级加密标准
  • RSA

名词解释

  • 分组加密:将明文切分成多个固定长度的分组
  • 块加密:加密算法只能处理固定长度的数据
  • 对称加密:解密与加密的使用同一个秘钥
  • 非对称加密:加密和解密使用不同的秘钥
  • 流密码:在分组加密中
  • 加密模式(mode):在分组加密中针对每个分组,有不同的处理方式。
  • 填充模式(padding):在分组加密或块加密中,数据长度无法不足时,需要按照一定模式对数据进行填充

填充模式

AES中的填充模式

PKCS5

分组数据缺少几个字节,就在数据的末尾填充几个字节的几,比如缺少5个字节,就在末尾填充5个字节的5

PKCS7

分组数据缺少几个字节,就在数据的末尾填充几个字节的0,比如缺少7个字节,就在末尾填充7个字节的0

NoPadding

不需要填充,保证数据长度满足加密算法的长度限定。

ISO10126Padding

填充字符串由一个字节序列组成,此字节序列的最后一个字节填充字节序列的长度,其余字节填充随机数据。

RSA中的填充模式

PKCS1_PADDING

输入:必须 比 RSA 钥模长(modulus) 短至少11个字节, 也就是 RSA_size(rsa) – 11, 如果输入的明文过长,必须切割, 然后填充

输出:和modulus一样长

PKCS1_OAEP_PADDING

输入:RSA_size(rsa) – 41
输出:和modulus一样长

NO_PADDING

不需要填充,保证数据长度满足加密算法的长度限定。

加密模式

  • ECB (Elecyronic Code Book,电子密码本模式)
  • CBC (Cipher Block Chaining,密码分组链接模式)
  • CFB (Cipher FeedBack Mode加密反馈)
  • OFB (Output FeedBack,输出反馈)
  • CTR (Counter ,计算器模式)

加密模式详解:

1、https://www.jianshu.com/p/5973a6b63593

2、https://www.jianshu.com/p/5973a6b63593

ECB

ECB模式是最基本的加密模式,即仅仅使用明文和密钥来加密数据,相同的明文块会被加密成相同的密文块,
这样明文和密文的结构将是完全一样的,就会更容易被破解,相对来说不是那么安全,因此很少使用。

CBC

而CBC模式则比ECB模式多了一个初始向量IV,加密的时候,第一个明文块会首先和初始向量IV做异或操作,
然后再经过密钥加密,然后第一个密文块又会作为第二个明文块的加密向量来异或,依次类推下去,
这样相同的明文块加密出的密文块就是不同的,明文的结构和密文的结构也将是不同的,因此更加安全,我们常用的就是CBC加密模式。

CFB

CFB的加密工作分为两部分:1、将一前段加密得到的密文再加密;2、将第1步加密得到的数据与当前段的明文异或。

OFB

OFB是先用块加密器生成密钥流,然后再将密钥流与明文流异或得到密文流,解密是先用块加密器生成密钥流,再将密钥流与密文流异或得到明文,由于异或操作的对称性所以加密和解密的流程是完全一样的。

java 中如何使用

java 提供的加密工具类在 javax.crypto.* 包下,提供统一的加密类Cipher 来完成。我们无法直接创建一个Cipher对象,需要通过Cipher.getInstance(String transformation)方法获取到Cipher实例,需要指定转换器的名称。转换器格式:Alg/Mode/Padding。 详解可见:https://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html#Cipher

工具类:sprite-utils

AES代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
Key sKeySpec = new SecretKeySpec(keyByte, "AES");

// 偏移量,默认偏移量为 new byte[16],建议不适用默认的偏移量
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(iv));

// 解密
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, params);

// 加密
cipher.init(Cipher.ENCRYPT_MODE, sKeySpec, params);

byte[] result = cipher.doFinal(content);

DES代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS7Padding");
Key sKeySpec = new SecretKeySpec(keyByte, "DES");

// 偏移量,默认偏移量为 new byte[16],建议不适用默认的偏移量
AlgorithmParameters params = AlgorithmParameters.getInstance("DES");
params.init(new IvParameterSpec(iv));

// 解密
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, params);

// 加密
cipher.init(Cipher.ENCRYPT_MODE, sKeySpec, params);

byte[] result = cipher.doFinal(content);

RSA代码

注:RSA是没有加密模式的,在获取Cipher时如果想指定填充模式,只能将模式指定为ECB才可以。java默认的填充模式是PKCS1Padding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
Key sKeySpec = new SecretKeySpec(keyByte, "RSA");

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

// 私钥加密
cipher.init(Cipher.ENCRYPT_MODE, keyFactory.generatePrivate(new PKCS8EncodedKeySpec(key)));

// 公钥加密
cipher.init(Cipher.ENCRYPT_MODE, keyFactory.generatePublic(new X509EncodedKeySpec(key)));

// 公钥解密
cipher.init(Cipher.DECRYPT_MODE, keyFactory.generatePublic(new X509EncodedKeySpec(key)));
// 私钥解密
cipher.init(Cipher.DECRYPT_MODE, keyFactory.generatePrivate(new PKCS8EncodedKeySpec(key)));
byte[] result = cipher.doFinal(content);

URL 编码

URI规则简介

 RFC3986文档规定,URI中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~ 4个特殊字符以及所有保留字符。

保留字符:

reserved    = gen-delims / sub-delims

gen-delims  = ":"  "/"  "?"  "#"  "["  "]"  "@"

sub-delims  = "!" "$"  "&"  "'"  "("  ")" "*" "+"  ","  ";"  "="

未保留字符:

unreserved  = 字母 / 数字 / "-" / "." / "_" / "~"

不安全字符:

  • 空格。
  • #:通常用于表示书签或者锚点
  • %:百分号本身用作对不安全字符进行编码时使用的特殊字符
  • 除保留字和未保留字符之外的其他字符

百分号编码

百分号编码的八位字节被编码为字符
三元组,由百分号“%”后跟两个
十六进制数字组成,后者表示该八位字节的数值。

pct-encoded = "%" HEXDIG HEXDIG

对于未保留字符,编码和不编码是等效的,即解析程序的解析结果是一致的。由于不安全字符可能引起解析程序的歧义,就需要对不安全字符进行百分号编码。

URL 编码

Url编码通常也被称为百分号编码。

SQL分页语句

Mysql

1
2
3
4
5
6
# 只需在查询语句后面加上 limit 
{sql} LIMIT {offset}, {pageSize}
```


## Oracle

SELECT * FROM (SELECT _rn.*, ROWNUM _rnum FROM ({sql}) _rn WHERE ROWNUM<={offset+pageSize}) WHERE _rnum> {offset}

1
2

## Sql Server

SELECT TOP {pageSize} _rn.* FROM (SELECT row_number() over({order by 语句}) AS _rnum,* FROM ({sql}) AS _rf ) AS _rn WHERE _rnum> {offset}

1
2
3
4


## Sql Server 2012
Sql Server 2012 对 sql 分页增加了新的支持

{sql} OFFSET ROW FETCH NEXT {pageSize} ROWS only

1
2

语法:

ORDER BY order_by_expression
[ COLLATE collation_name ]
[ ASC | DESC ]
[ ,…n ]
[ ]

::=
{
OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }
[
FETCH { FIRST | NEXT } {integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY
]
}

1
2

## PostgreSQL

{sql} LIMIT {pageSize} OFFSET {offset}

Unicode 了解

简介

Unicode(世界统一码)是由世界统一码联盟制定的一套字符编码,其中包含了世界绝大部分的语言文字,还包含了表情文字。在Unicode 2.0之后(最新Unicode 11.0),Unicode编码与UCS(Universal Coded Character Set)基本保持一致。Uincode 版本列表,点击查看

Unicode 编码提供了一组基本单元编码,为每个基本单元分配一个唯一的编码点(Code Point)。一个文本元素是有一个或多个基本单元组成。例如法语中的Ç 可以看做是由 C 和¸ 组合成的。

名词解释

  • Basic Multilingual Plane (BMP) 基础多语言层面
  • Supplementary Multilingual Plane (SMP) 多语言补充层皮
  • Supplementary Ideographic Plane (SIP) 表意文字补充平面
  • Supplementary Special-purpose Plane (SSP) 特别用途补充平面
  • Private Use Area-A Plane (PUA-A) 私人使用区-A平面
  • Private Use Area-B Plane (PUA-B) 私人使用区-B平面
  • CJK 中国、日本、韩国 三个国加的简称
  • CJKV 中国、日本、韩国、越南 四个国加的简称
  • RTL right-to-left 从右到左
  • BE big-endian 大端序列, 高位在前(低地址),低在后(高地址)
  • LE little-endian 小端序列, 一个单元在计算机中的存放时按照低位在前(低地址),高位在后(高地址)的模式存放。

分配情况

整体

BMP 分配情况

图片截自UnicodeStandard-11.0.pdf

基础层面中D800-DFFF 区间为代理区间,区间内的代码点不表示任何字符。一个UTF-16编码只能表示BMP中的字符,无法表示BMP外的其他层面。通过代理区我们可以使用两个UTF-16编码来表示BMP外层面的一个字符。

SMP 分配情况

图片截自UnicodeStandard-11.0.pdf

编码的实现方式

计算机处理信息的最小单元为字节,而一个字节无法表示Unicode中的所有字符。为了表示所有的字符,就需要一种实现方式将Unicode中的字符编码转换为计算机可以处理的字节序列。

Unicode编码的实现方式有:

  • UTF-8
  • UTF-16
  • UTF-32
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×