[Java 安全]加密算法

Base64编码

算法简述

定义

Base64内容传送编码是一种以任意8位字节序列组合的描述形式,这种形式不易被人直接识别。

Base64是一种很常见的编码规范,其作用是将二进制序列转换为人类可读的ASCII字符序列,常用在需用通过文本协议(比如HTTPSMTP)来传输二进制数据的情况下。Base64并不是加密解密算法,尽管我们有时也听到使用Base64来加密解密的说法,但这里所说的加密与解密实际是指编码(encode)和解码(decode)的过程,其变换是非常简单的,仅仅能够避免信息被直接识别。

 

原理

Base64算法主要是将给定的字符以字符编码(ASCII码,UTF-8)对应的十进制数为基准,做编码操作:

(1)将给定的字符串以字符为单位,转换为对应的字符编码。

(2)将获得字符编码转换为二进制

(3)对二进制码做分组转换,每3个字节为一组,转换为每46位二进制位一组(不足6位时低位补0)。这是一个分组变化的过程,38位二进制码和46位二进制码的长度都是24位(3*8 = 4*6 = 24)。

(4)对获得的4-6二进制码补位,向6位二进制码添加2位高位0,组成48位二进制码。

(5)对获得的4-8二进制码转换为十进制码。

(6)将获得的十进制码转换为Base64字符表中对应的字符。

Base64编码表

索引

对应字符

索引

对应字符

索引

对应字符

索引

对应字符

0

A

17

R

34

i

51

z

1

B

18

S

35

j

52

0

2

C

19

T

36

k

53

1

3

D

20

U

37

l

54

2

4

E

21

V

38

m

55

3

5

F

22

W

39

n

56

4

6

G

23

X

40

o

57

5

7

H

24

Y

41

p

58

6

8

I

25

Z

42

q

59

7

9

J

26

a

43

r

60

8

10

K

27

b

44

s

61

9

11

L

28

c

45

t

62

+

12

M

29

d

46

u

63

/

13

N

30

e

47

v

 

 

14

O

31

f

48

w

 

 

15

P

32

g

49

x

 

 

16

Q

33

h

50

y

 

 

 

应用

Base64编码可用于在HTTP环境下传递较长的标识信息。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到,算是起到一个加密的作用。

然而,标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。

为解决此问题,可采用一种用于URL的改进Base64编码,它不仅在末尾填充'='号,并将标准Base64中的“+”和“/”分别改成了“-”和“_”,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。

另有一种用于正则表达式的改进Base64变种,它将“+”和“/”改成了“!”和“-”,因为“+,*”以及前面在IRCu中用到的“[”和“]”在正则表达式中都可能具有特殊含义。

此外还有一些变种,它们将“+/”改为“_-”或“._”(用作编程语言中的标识符名称)或“.-”(用于XML中的Nmtoken)甚至“_:”(用于XML中的Name)。

 

算法实现

commons-codec开源包提供了对于Base64的实现,推荐使用。

<dependency>
  <groupId>
commons-codec</groupId>
  <artifactId>
commons-codec</artifactId>
  <version>
1.10</version>
</dependency>

 

范例

注:在commons-codec包中的Base64这个类中提供了Base64的编码、解码方式。

其中,encodeBase64提供的是标准的Base64编码方式;encodeBase64URLSafe提供了URL安全的Base64编码方式(将 /替换为 -  _)。

package org.zp.javase.security.encrypt;

import 
org.apache.commons.codec.binary.Base64;
import 
java.io.UnsupportedEncodingException;

public class 
Base64Demo {
    
public static void main(String[] args) throws UnsupportedEncodingException {
        String url = 
"https://www.baidu.com/s?wd=Base64&rsv_spt=1&rsv_iqid=0xa9188d560005131f&issp=1&f=3&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=1&rsv_sug1=1&rsv_sug7=001&rsv_sug2=1&rsp=0&rsv_sug9=es_2_1&rsv_sug4=2153&rsv_sug=9";
        
// byte[] encoded = Base64.encodeBase64(url.getBytes("UTF8")); // 标准的Base64编码
        
byte[] encoded = Base64.encodeBase64URLSafe(url.getBytes("UTF8"))// URL安全的Base64编码
        
byte[] decoded = Base64.decodeBase64(encoded);
        
System.out.println("url:" + url);
        
System.out.println("encoded:" new String(encoded));
        
System.out.println("decoded:" new String(decoded));
    
}
}

 

对称加密

算法简述

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

 

特点

优点:

计算量小、加密速度快、加密效率高。

缺点:

算法是公开的,安全性得不到保证。

通信双方每次使用对称加密算法时,都需要使用其他人不知道的惟一密钥,这会使得通信双方所拥有的密钥数量呈几何级数增长,密钥管理成为用户的负担。对称加密算法在分布式网络系统上使用较为困难,主要是因为密钥管理困难,使用成本较高。

而与公钥、密钥加密算法比起来,对称加密算法能够提供加密和认证却缺乏了签名功能,使得使用范围有所缩小。

 

原理

对称加密要求加密与解密使用同一个密钥,解密是加密的逆运算。由于加密、解密使用同一个密钥,这要求通信双方必须在通信前商定该密钥,并妥善保存该密钥。

对称加密体制分为两种:

一种是对明文的单个位(或字节)进行运算,称为流密码,也称为序列密码;

一种是把明文信息划分为不同的组(或块)结构,分别对每个组(或块)进行加密、解密,称为分组密码。

 

假设甲乙方作为通信双方。假定甲乙双方在消息传递前已商定加密算法,欲完成一次消息传递需要经过如下步骤。

工作模式

DES算法的工作模式为例,DES算法根据其加密算法所定义的明文分组的大小(56位),将数据分割成若干56位的加密区块,再以加密区块为单位,分别进行加密处理。如果最后剩下不足一个区块的大小,称之为短块。短块的处理方法有填充法、流密码加密法、密文挪用技术。

根据数据加密时每个加密区块见得关联方式来区分,可以分为以下种工作模式:

(1)  电子密码本模式(Electronic Code Book, ECB)

用途:适合加密密钥,随机数等短数据。例如,安全地传递DES密钥,ECB是最合适的模式。

(2)  密文链接模式(Cipher Booki Chaining, CBC)

用途:可加密任意长度的数据,适用于计算产生检测数据完整性的消息认证MAC

(3)  密文反馈模式(Cipher Feed Back, CFB)

用途:因错误传播无界,可以用于检查发现明文密文的篡改。

(4)  输出反馈模式(Output Feed Back, OFB)

用途:使用于加密冗余性较大的数据,比如语音和图像数据。

AES算法除了以上4中模式外,还有一种新的工作模式:

(5)  计数器模式(Counter, CTR)

用途:适用于各种加密应用。

本文对于各种工作模式的原理展开描述。个人认为,作为工程应用,了解其用途即可。

 

填充方法

Java中对称加密对于短块的处理,一般是采用填充方式。

常采用的是:NoPadding(不填充)、Zeros填充(0填充)、PKCS5Padding填充。

ZerosPadding

方式:全部填充为0的字节

结果如下:

F1 F2 F3 F4 F5 F6 F7 F8 //第一块

F9 00 00 00 00 00 00 00 //第二块

 

PKCS5Padding

方式:每个填充的字节都记录了填充的总字节数

结果如下:

F1 F2 F3 F4 F5 F6 F7 F8 //第一块

F9 07 07 07 07 07 07 07 //第二块

 

常用算法

对称加密算法主要有DES3DESTripleDES)、AESIDEARC2RC4RC5Blowfish等。

 

算法实现

基于密钥加密的流程(DESDESedeAESIDEA

DESDESedeAESIDEA等算法都是基于密钥加密的对称加密算法,它们的实现流程也基本一致。步骤如下:

(1)生成密钥

KeyGenerator kg = KeyGenerator.getInstance("DES");
SecureRandom random = new SecureRandom();
kg.init(random);
SecretKey secretKey = kg.generateKey();

建议使用随机数来初始化密钥的生成。

 

(2)初始化密码对象

Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODEsecretKey);

ENCRYPT_MODE:加密模式

DECRYPT_MODE:解密模式

 

(3)执行

String plaintext = "Hello World";
byte
[] ciphertext = cipher.doFinal(plaintext.getBytes());

 

完整实例

一个完整的DES加密解密范例

import org.bouncycastle.util.encoders.Base64;
import 
org.zp.javase.security.encode.Encode;

import 
javax.crypto.BadPaddingException;
import 
javax.crypto.Cipher;
import 
javax.crypto.IllegalBlockSizeException;
import 
javax.crypto.KeyGenerator;
import 
javax.crypto.NoSuchPaddingException;
import 
javax.crypto.spec.IvParameterSpec;
import 
java.security.InvalidAlgorithmParameterException;
import 
java.security.InvalidKeyException;
import 
java.security.Key;
import 
java.security.NoSuchAlgorithmException;
import 
java.security.NoSuchProviderException;
import 
java.security.SecureRandom;

/**
 * @Title DESCoder
 * @Description DES
安全编码:是经典的对称加密算法。密钥仅56位,且迭代次数偏少。已被视为并不安全的加密算法。
 * @Author 
victor
 * @Date 2016年7月14日
 */
public class DESCoder implements Encode {
    
public static final String KEY_ALGORITHM_DES "DES";
    public static final 
String CIPHER_DES_DEFAULT "DES";
    public static final 
String CIPHER_DES_ECB_PKCS5PADDING "DES/ECB/PKCS5Padding"// 算法/模式/补码方式
    
public static final String CIPHER_DES_CBC_PKCS5PADDING "DES/CBC/PKCS5Padding";
    public static final 
String CIPHER_DES_CBC_NOPADDING "DES/CBC/NoPadding";
    private static final 
String SEED "%%%today is nice***"// 用于生成随机数的种子

    
private Key key;
    private 
Cipher cipher;
    private 
String transformation;

    public 
DESCoder() throws NoSuchAlgorithmExceptionNoSuchPaddingExceptionNoSuchProviderException {
        
this.key = initKey();
        this
.cipher = Cipher.getInstance(CIPHER_DES_DEFAULT);
        this
.transformation CIPHER_DES_DEFAULT;
    
}

    
public DESCoder(String transformation)
            
throws NoSuchAlgorithmExceptionNoSuchPaddingExceptionNoSuchProviderException {
        
this.key = initKey();
        this
.cipher = Cipher.getInstance(transformation);
        this
.transformation = transformation;
    
}

    
/**
     * @Title decrypt
     * @Description 
解密
     * @Author 
victor
     * @Date 2016年7月20日
     * @param 
input 密文
     * @return byte[] 明文
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     * @throws InvalidAlgorithmParameterException
     */
    
public byte[] decrypt(byte[] input) throws InvalidKeyExceptionIllegalBlockSizeExceptionBadPaddingException,
            
InvalidAlgorithmParameterException {
        
if (transformation.equals(CIPHER_DES_CBC_PKCS5PADDING) || transformation.equals(CIPHER_DES_CBC_NOPADDING)) {
            
cipher.init(Cipher.DECRYPT_MODEkey, new IvParameterSpec(getIV()));
        
else {
            
cipher.init(Cipher.DECRYPT_MODEkey);
        
}
        
return cipher.doFinal(input);
    
}

    
/**
     * @Title encrypt
     * @Description 
加密
     * @Author 
victor
     * @Date 2016年7月20日
     * @param 
input 明文
     * @return byte[] 密文
     * @throws InvalidKeyException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     * @throws InvalidAlgorithmParameterException
     */
    
public byte[] encrypt(byte[] input) throws InvalidKeyExceptionIllegalBlockSizeExceptionBadPaddingException,
            
InvalidAlgorithmParameterException {
        
if (transformation.equals(CIPHER_DES_CBC_PKCS5PADDING) || transformation.equals(CIPHER_DES_CBC_NOPADDING)) {
            
cipher.init(Cipher.ENCRYPT_MODEkey, new IvParameterSpec(getIV()));
        
else {
            
cipher.init(Cipher.ENCRYPT_MODEkey);
        
}
        
return cipher.doFinal(input);
    
}

    
/**
     * @Title initKey
     * @Description 
根据随机数种子生成一个密钥
     * @Author victor
     * @Date 2016年7月14日
     * @Return Key
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     */
    
private Key initKey() throws NoSuchAlgorithmExceptionNoSuchProviderException {
        
// 根据种子生成一个安全的随机数
        
SecureRandom secureRandom = null;
        
secureRandom = new SecureRandom(SEED.getBytes());

        
KeyGenerator keyGen = KeyGenerator.getInstance(KEY_ALGORITHM_DES);
        
keyGen.init(secureRandom);
        return 
keyGen.generateKey();
    
}

    
private byte[] getIV() {
        String iv = 
"01234567"// IV length: must be 8 bytes long
        
return iv.getBytes();
    
}

    
public static void main(String[] args) throws Exception {
        DESCoder aes = 
new DESCoder(CIPHER_DES_CBC_PKCS5PADDING);

        
String msg = "Hello World!";
        
System.out.println("原文: " + msg);
        byte
[] encoded = aes.encrypt(msg.getBytes("UTF8"));
        
String encodedBase64 = Base64.toBase64String(encoded);
        
System.out.println("密文: " + encodedBase64);

        byte
[] decodedBase64 = Base64.decode(encodedBase64);
        byte
[] decoded = aes.decrypt(decodedBase64);
        
System.out.println("明文: " new String(decoded));
    
}
}

结果:

原文: Hello World!
密文: TtnEu9ezNQtxFKpmq/
37Qw==
明文: Hello World!

 

基于口令加密的流程(PBE

DESDESedeAESIDEA这几种算法的应用模型几乎如出一辙。

但是,并非所有对称加密算法都是如此。

基于口令加密(Password Based Encryption, PBE)是一种基于口令加密的算法。其特点是:口令由用户自己掌管,采用随机数(这里叫做盐)杂凑多重加密等方法保证数据的安全性。

PBE没有密钥概念,密钥在其他对称加密算法中是经过计算得出的,PBE则使用口令替代了密钥。

流程:

 

步骤如下:

(1)产生盐

SecureRandom secureRandom = new SecureRandom();
byte
[] salt = secureRandom.generateSeed(8)// 盐长度必须为8字节

 

(2)根据密码产生Key

String password = "123456";
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
SecretKey secretKey = keyFactory.generateSecret(keySpec);

 

(3)初始化加密或解密对象

PBEParameterSpec paramSpec = new PBEParameterSpec(saltITERATION_COUNT);
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODEsecretKeyparamSpec);

 

(4)执行

byte[] plaintext = "Hello World".getBytes();
byte
[] ciphertext = cipher.doFinal(plaintext);

 

非对称加密

算法简述

非对称加密算法和对称加密算法的主要差别在于非对称加密算法用于加密和解密的密钥是不同的。一个公开,称为公钥(public key);一个保密,称为私钥(private key)。因此,非对称加密算法也称为双钥加密算法或公钥加密算法。

 

特点

优点

非对称加密算法解决了对称加密算法的密钥分配问题,并极大地提高了算法安全性。

 

缺点

算法比对称算法更复杂,因此加密、解密速度都比对称算法慢很多。

 

原理

非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。

另一方面,甲方可以使用乙方的公钥对机密信息进行签名后再发送给乙方;乙方再用自己的私匙对数据进行验证。

甲方只能用其私钥解密,由其公钥加密后的任何信息。 非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要。

 

常用算法

DH(Diffie-Hellman,密钥交换算法)RSA

 

算法实现

完整范例

import org.apache.commons.codec.binary.Base64;

import 
javax.crypto.Cipher;
import 
java.security.KeyFactory;
import 
java.security.KeyPair;
import 
java.security.KeyPairGenerator;
import 
java.security.PrivateKey;
import 
java.security.PublicKey;
import 
java.security.spec.PKCS8EncodedKeySpec;
import 
java.security.spec.X509EncodedKeySpec;

public class 
RSACoder {
    
private final static String KEY_ALGORITHM "RSA";
    private 
KeyPair keyPair;

    public 
RSACoder() throws Exception {
        
this.keyPair = initKeyPair();
    
}

    
public byte[] encryptByPublicKey(byte[] plaintext, byte[] key) throws Exception {
        X509EncodedKeySpec keySpec = 
new X509EncodedKeySpec(key);
        
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        
PublicKey publicKey = keyFactory.generatePublic(keySpec);
        
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        
cipher.init(Cipher.ENCRYPT_MODEpublicKey);
        return 
cipher.doFinal(plaintext);
    
}

    
public byte[] encryptByPrivateKey(byte[] plaintext, byte[] key) throws Exception {
        PKCS8EncodedKeySpec keySpec = 
new PKCS8EncodedKeySpec(key);
        
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        
cipher.init(Cipher.ENCRYPT_MODEprivateKey);
        return 
cipher.doFinal(plaintext);
    
}

    
public byte[] decryptByPublicKey(byte[] ciphertext, byte[] key) throws Exception {
        X509EncodedKeySpec keySpec = 
new X509EncodedKeySpec(key);
        
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        
PublicKey publicKey = keyFactory.generatePublic(keySpec);
        
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        
cipher.init(Cipher.DECRYPT_MODEpublicKey);
        return 
cipher.doFinal(ciphertext);
    
}

    
public byte[] decryptByPrivateKey(byte[] ciphertext, byte[] key) throws Exception {
        PKCS8EncodedKeySpec keySpec = 
new PKCS8EncodedKeySpec(key);
        
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        
cipher.init(Cipher.DECRYPT_MODEprivateKey);
        return 
cipher.doFinal(ciphertext);
    
}

    
private KeyPair initKeyPair() throws Exception {
        
// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
        
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        
// 初始化密钥对生成器,密钥大小为1024位
        
keyPairGen.initialize(1024);
        
// 生成一个密钥对
        
return keyPairGen.genKeyPair();
    
}

    
public static void main(String[] args) throws Exception {
        String msg = 
"Hello World!";
        
RSACoder coder = new RSACoder();
        
// 私钥加密,公钥解密
        
byte[] ciphertext = coder.encryptByPrivateKey(msg.getBytes("UTF8")coder.keyPair.getPrivate().getEncoded());
        byte
[] plaintext = coder.decryptByPublicKey(ciphertextcoder.keyPair.getPublic().getEncoded());

        
// 公钥加密,私钥解密
        
byte[] ciphertext2 = coder.encryptByPublicKey(msg.getBytes()coder.keyPair.getPublic().getEncoded());
        byte
[] plaintext2 = coder.decryptByPrivateKey(ciphertext2coder.keyPair.getPrivate().getEncoded());

        
System.out.println("原文:" + msg);
        
System.out.println("公钥:" + Base64.encodeBase64URLSafeString(coder.keyPair.getPublic().getEncoded()));
        
System.out.println("私钥:" + Base64.encodeBase64URLSafeString(coder.keyPair.getPrivate().getEncoded()));

        
System.out.println("============== 私钥加密,公钥解密 ==============");
        
System.out.println("密文:" + Base64.encodeBase64URLSafeString(ciphertext));
        
System.out.println("明文:" new String(plaintext));

        
System.out.println("============== 公钥加密,私钥解密 ==============");
        
System.out.println("密文:" + Base64.encodeBase64URLSafeString(ciphertext2));
        
System.out.println("明文:" new String(plaintext2));
    
}
}

结果:

原文:Hello World!
公钥:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVN2mWAMdatpo2l8dwavaX2VC8mRleVTdjwjyahsyCE6UxkdqHsKD6Ecq3OBbuJhEfHxnr7MAD_zoE6zalFs7_si09XTgpVFsFCztPXJpPw-rpQdvaaxYEXJHkY07M_DBrxh1URg2gQl9dEDaruIFrZ12ugTwwEkLA1K_LN7yZrwIDAQAB
私钥:MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJU3aZYAx1q2mjaXx3Bq9pfZULyZGV5VN2PCPJqGzIITpTGR2oewoPoRyrc4Fu4mER8fGevswAP_OgTrNqUWzv-yLT1dOClUWwULO09cmk_D6ulB29prFgRckeRjTsz8MGvGHVRGDaBCX10QNqu4gWtnXa6BPDASQsDUr8s3vJmvAgMBAAECgYBvU1M8LcKOJFQzzNNoRPVLX0AEJXkuzwcvL1hFtbJYjc2eiQHwYFAJokKKpZc-ADqf7HVLdmvfz4h66P3w925hYHjSF3cs6jiibI7fc9lrdrJLMpv44phPlRCiIanD-U6pyN3bZxRl4Giuz5uGL0SVU6Dxh2Sw7mtnvUBbHCyyaQJBAOixpR-t81Qnpdy4jlbZL8ufTTF1TzlSh0NEDB4tlpHlVolVmZB2M-rdJ3nP8fJXazdsGZMP0q38vgiN2HHMtxsCQQCkKWAaA6KxKNbj0mJDSP1p4qUJ4EAcgXBz4B_PKMZa3ZU2CdmFlhlLRRTOIjZX2VC6IjHKWssa-3V2EqBzCSz9AkBsiK9kH1anofaTBOIfUB4i86KltvnE2uGMVmjwioL4eefrFqoR35BHs-99uag4SN4Rc7JaDb9Ot9xLUR3rtniRAkB8dFXEQx9Teie4HmaapjpgzQ_b9eQE-GjdoHvdHQeMGdMmXb9IVGwmsV-9ixhx73IROx1OURkMArmhYyu7KqitAkBkeQ-7AYOIROJnTUSQTMUELUmZFF1Io_SJGXyRYLgDqz7JCmmhfH7sNm8Gcn6f2VWg-U2D9-G5IHO-vHfz2DS6
============== 私钥加密,公钥解密 ==============
密文:U2otXypy1Fg4wcXK187xAuOxWM88oORVDJfaNxvG74Q_rqZ-sT4fEZYLZO80KmsWiufkJbD9Gskgkg7dRPRCwG90pRaU3PD9_sTmksN0v8MUwCX2p80zUeG3gWU6BJwMMUZrltJaHFbKn-BhzoNrn3Q-4BJA8lt6-cKtH0TPeN4
明文:Hello World!
============== 公钥加密,私钥解密 ==============
密文:O_rknvo12qaFfWieyTI_Ay8_ph49y3V4jJVs1BykpI81GM3ozCPSnOjHbtdWdjPtgJHFfCjbspAnIT2eM4PtJldIJg6k_2HZCmCCaheUj2pxcvkrhb6GdhSlH-K2FhFGAnlxUAp-3tZpYpxzAteEw1-suldelHdikrCV_uXxAEM
明文:Hello World!

 

术语

明文(Plaintext):指待加密信息。明文可以是文本文件、图片文件、二进制数据等。

密文(Ciphertext):指经过加密后的明文。密文通常以文本、二进制等形式存在。

加密(Encryption):指将明文转换为密文的过程。

解密(Decryption):指将密文转换为明文的过程。

加密密钥(Encryption Key):指通过加密算法进行加密操作用的密钥。

解密密钥(Decryption Key):指通过解密算法进行解密操作用的密钥。

信道(Channel):通信的通道,是信号传输的媒介。


本文转自静默虚空博客园博客,原文链接:http://www.cnblogs.com/jingmoxukong/p/5688306.html,如需转载请自行联系原作者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/392704.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2个字段并在一次插入一个字段里面_elasticsearch外用与内观(二)-当插入文档时,elasticsearch都在做什么...

Previous: elasticsearch外用与内观(一)-常用功能与使用方法 在了解了es的基本用法之后&#xff0c;我们再来看看当插入文档数据时&#xff0c;elasticsearch都在做什么。首先&#xff0c;es的索引只是一个逻辑概念&#xff0c;实际上是由一个个物理分片组成的,每个分片就是一个…

学习Spring Data JPA

简介 Spring Data 是spring的一个子项目&#xff0c;在官网上是这样解释的&#xff1a; Spring Data 是为数据访问提供一种熟悉且一致的基于Spring的编程模型&#xff0c;同时仍然保留底层数据存储的特​​殊特性。它可以轻松使用数据访问技术&#xff0c;可以访问关系和非关系…

git 常用commands(转)

常用 Git 命令清单 作者&#xff1a; 阮一峰 日期&#xff1a; 2015年12月 9日 我每天使用 Git &#xff0c;但是很多命令记不住。 一般来说&#xff0c;日常使用只要记住下图6个命令&#xff0c;就可以了。但是熟练使用&#xff0c;恐怕要记住60&#xff5e;100个命令。 下面是…

检查集群状态命令_轻松管理Kubernetes集群的7个工具

Kubernetes正在不断加快在云原生环境的应用&#xff0c;但如何以统一、安全的方式对运行于任何地方的Kubernetes集群进行管理面临着挑战&#xff0c;而有效的管理工具能够大大降低管理的难度。K9sk9s是基于终端的资源仪表板。它只有一个命令行界面。无论在Kubernetes仪表板Web …

vscode 模糊部分代码_本周 GitHub 速览:您的代码有声儿吗?(Vol.38)

作者&#xff1a;HelloGitHub-小鱼干摘要&#xff1a;还记得花式夸赞程序员的彩虹屁插件 vscode-rainbow-fart 吗&#xff1f;它后续有人啦&#xff01;JazzIt 同它的前辈 vscode-rainbow-fart 一样&#xff0c;是一个能让代码“发声”的工具&#xff0c;它会在脚本运行成功或者…

C语言递归实现二叉树(二叉链表)的三种遍历和销毁操作(实验)

今天写的是二叉树操作的实验&#xff0c;这个实验有三个部分&#xff1a; ①建立二叉树&#xff0c;采用二叉链表结构 ②先序、中序、后续遍历二叉树&#xff0c;输出节点值 ③销毁二叉树 二叉树的节点结构定义 typedef struct BiTNode //二叉树的节…

Django 入门项目案例开发(中)

关注微信公众号&#xff1a;FocusBI 查看更多文章&#xff1b;加QQ群&#xff1a;808774277 获取学习资料和一起探讨问题。 昨天已经描述了如何搭建Django的开发环境&#xff0c;今天描述业务流程&#xff0c;具体我们要实现一个什么样的业务&#xff1b; 以下的业务都是假设的…

纵横公路造价软件学习_通辽分公司组织开展2020年 养护工程造价预算培训

为进一步提高养护员工业务水平和业务素质&#xff0c;提升熟练掌握信息化公路工程造价预算&#xff0c;11月5日&#xff0d;11月8日期间,通辽分公司组织开展了2020年养护工程造价预算培训。养护科全体人员、基层所站统计人员共计16人参加培训。本次培训邀请了纵横公路工程造价管…

arcgis插值不覆盖区划图_ArcGIS绘图—空气质量站点数据插值绘制等值线图

作者&#xff1a;吴琳&#xff1b;陈天舒&#xff0c;山东大学环境科学&#xff08;大气化学&#xff09;博士在读数据&#xff08;Excel格式&#xff09;&#xff1a;多站点污染物数据&#xff08;国&#xff0c;省&#xff0c;市控点&#xff09;&#xff0c;站点经纬度信息绘…

JavaScript覆盖率统计实现

主要需求 1、 支持browser & nodejs 由于javascript既能够在浏览器环境执行&#xff0c;也能够在nodejs环境执行&#xff0c;因此须要能够统计两种环境下单元測试的覆盖率情况。 2、 透明、无缝 用户写单元測试用例的时候&#xff0c;不须要为了支持覆盖率统计多写代码&…

单元格内容分列多行_姓名太多,放在一列打印时浪费纸张,可以分成多行多列打印...

在日常工作中&#xff0c;往往会碰到这种情况(如下图)&#xff1a;只有一列数据&#xff0c;而且比较多&#xff0c;如果打印起来就浪费纸张&#xff0c;然后复制、粘贴把表格变成几列&#xff0c;方便打印。今天小编和大家分享不用复制、粘贴&#xff0c;就能快速完成一列分成…

Java中接口、抽象类与内部类学习

2019独角兽企业重金招聘Python工程师标准>>> Java中接口、抽象类与内部类学习 接口与内部类为我们提供了一种将接口与实现分离的更加结构化的方法。 抽象类和抽象方法 抽象方法&#xff1a;仅有声明而没有方法体。 抽象类&#xff1a;包含一个或多个抽象方法的类&am…

docker导入镜像 liunx_docker扫盲?面试连这都不会就等着挂吧

推荐阅读&#xff1a;java喵&#xff1a;6大面试技能树&#xff1a;JAVA基础JVM算法数据库计算机网络操作系统​zhuanlan.zhihu.com一只Tom猫&#xff1a;都是“Redis惹的祸”&#xff0c;害我差点挂在美团三面&#xff0c;真是“虚惊一场”&#xff01;​zhuanlan.zhihu.com现…

Linux iptables:规则原理和基础

什么是iptables&#xff1f; iptables是Linux下功能强大的应用层防火墙工具&#xff0c;但了解其规则原理和基础后&#xff0c;配置起来也非常简单。 什么是Netfilter&#xff1f; 说到iptables必然提到Netfilter&#xff0c;iptables是应用层的&#xff0c;其实质是一个定义规…

太阳系八大行星碰撞的视频_火星的身世:从太阳系的起源说起

大约46亿年前盘状的太阳星云从一大片又冷又暗的气体云中诞生太阳自己并没有任何暴露确切年龄的线索&#xff0c;我们之所以能够知道太阳系的“生日”&#xff0c;是因为迄今从陨石中找到的最古老固体物质&#xff0c;年龄约为45.68亿年。一般认为&#xff0c;太阳系的各个地方是…

博科查看光功率_法拉第旋光器:非互易性旋转光的偏振

法拉第旋光器是利用法拉第效应制作的光学器件&#xff0c;当入射光正向(或反向)进入旋光器时&#xff0c;入射光偏振面会发生旋转。法拉第效应1845年&#xff0c;法拉第发现&#xff1a;当一束平面偏振光通过置于磁场中的磁光介质时&#xff0c;平面偏振光的偏振面就会随着平行…

ps怎么对比原图快捷键_PS学习之旅:ps如何制作满天星,让你夜晚的天空图片更美...

ps学习之旅&#xff0c;本文介绍关于如何利用ps软件来制作满天星&#xff0c;让你夜晚的天空图片更美&#xff0c;操作很简单哦。1工具/原料Adobe Photoshop CS6软件图片一张2效果展示原图&#xff1a;效果图&#xff1a;3方法/步骤(1)打开PS&#xff0c;选择你想要加星星的一张…

永磁直驱风力发电机结构图_国内首台10MW海上永磁直驱风力发电机研制成功

2019首届新能源产业投融资论坛2019年10月25日周老师&#xff1a;157129595968月21日&#xff0c;具有完全自主知识产权、国内首台10MW海上永磁直驱风力发电机在东方电气集团东方电机有限公司研制成功&#xff0c;以此优异成绩向新中国成立70周年献礼。10MW海上永磁直驱风力发电…

struts2官方 中文教程 系列六:表单验证

先贴个本帖的地址&#xff0c;以免被爬&#xff1a;struts2教程 官方系列六&#xff1a;表单验证 即 http://www.cnblogs.com/linghaoxinpian/p/6906720.html 下载本章节代码 介绍 在本教程中&#xff0c;我们将探索使用Struts2来验证用户在表单上的输入。有两种方法可以来进…

c++ dll 类使用_在.Net Core 中使用钩子

目录前言什么是钩子使用钩子3. 挂载多个钩子4. 在钩子中加载额外的程序集5. 在 Asp.Net Web Api 项目中使用钩子结束语演示代码下载前言Host startup hook&#xff0c;是2.2中提供的一项新的功能&#xff0c;通过使用主机启动钩子&#xff0c;允许开发人员在不修改代码的情况下…