1、加密解密基本概念
通讯的加密和解密主要涉及将原始信息(明文)转换为不可直接理解的格式(密文),以及将密文还原为原始信息的过程。这一过程通常包括三个基本步骤:加密、传输和解密,其中加密和解密分别使用特定的算法和密钥进行。
2、加密
加密是将原始信息(明文)通过特定的算法和密钥转换为密文的过程。这个过程旨在保护信息在传输过程中不被未经授权的第三方获取或理解。加密方法包括但不限于替换密码(如凯撒密码)、转换密码(如无线电扩频通信)以及使用专门的加密机进行加密。随着技术的发展,现代加密技术还包括对称加密(如DES、AES 、RC4算法)和非对称加密(如RSA算法),后者通常用于数字签名和公钥基础设施中。
2.1对称加密
加密和解密过程使用同一个密钥。这意味着发送方使用密钥对要传输的数据进行加密,接收方则使用相同的密钥对加密后的数据进行解密,以恢复原始数据。
由于加密和解密使用的是同一个密钥,且算法通常较为简单,因此加密和解密的速度较快,适合对大量数据进行加密和解密。
public class AesExample {
public static void main(String[] args) throws Exception {
// 生成密钥
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128); // 可选:128, 192, 256
SecretKey secretKey = keyGen.generateKey();
byte[] key = secretKey.getEncoded();
// 加密
String plaintext = "Hello, World!";
Cipher encryptCipher = Cipher.getInstance("AES");
encryptCipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"));
byte[] encryptedBytes = encryptCipher.doFinal(plaintext.getBytes());
String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
System.out.println("Encrypted Text: " + encryptedText);
// 解密
Cipher decryptCipher = Cipher.getInstance("AES");
decryptCipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"));
byte[] decryptedBytes = decryptCipher.doFinal(Base64.getDecoder().decode(encryptedText));
String decryptedText = new String(decryptedBytes);
System.out.println("Decrypted Text: " + decryptedText);
}
}
2.2非对称加密
采用两个密钥,即公钥和私钥。公钥用于加密数据,私钥则用于解密数据。公钥可以公开分享,而私钥则必须保密。
加密和解密使用的是不同的密钥,且算法相对复杂,因此加密和解密的速度较慢,只适合对少量数据进行加密和解密。
3、解密
解密是接收方使用相应的解密算法和密钥将收到的密文还原为原始明文的过程。解密是加密的反向操作,需要使用与加密过程中相同的算法和密钥。解密的成功与否取决于密钥的保密程度以及加密算法的安全性。如果密钥被泄露或算法被破解,那么加密的信息就不再安全。
3.1对称加密的解密
对称加密,也称为单密钥加密,在加密过程中,数据发送方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,生成复杂的加密密文发送出去,接收方在收到密文后,需要使用与加密时相同的密钥以及相应算法的逆算法对密文进行解密,才能恢复成原始的明文数据。
3.2非对称加密的解密
非对称加密使用一对密钥:公钥和私钥。公钥可以公开分享,而私钥则必须保密。在加密过程中,发送方使用接收方的公钥对要传输的数据进行加密,然后将加密后的密文发送给接收方,接收方在收到密文后,使用自己的私钥对密文进行解密,以恢复成原始的明文数据。由于私钥是保密的,且公钥无法推导出私钥,因此即使公钥被泄露,加密的数据仍然安全。
public class RsaExample {
public static void main(String[] args) throws Exception {
// 生成密钥对
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);
KeyPair keyPair = keyGen.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 加密
String plaintext = "Hello, World!";
Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedBytes = encryptCipher.doFinal(plaintext.getBytes());
String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
System.out.println("Encrypted Text: " + encryptedText);
// 解密
Cipher decryptCipher = Cipher.getInstance("RSA");
decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedBytes = decryptCipher.doFinal(Base64.getDecoder().decode(encryptedText));
String decryptedText = new String(decryptedBytes);
System.out.println("Decrypted Text: " + decryptedText);
}
}
4、加签
加签是指在数据传输前,使用密钥对数据进行加密生成数字签名的过程。这个过程包括使用私钥对数据进行加密,生成数字签名,并将数字签名与原始数据一起发送给接收方。数字签名的生成过程需要使用私钥,而验证过程则使用相应的公钥。加签的目的是为了证明消息的完整性和真实性,只有拥有密钥的人才能生成数字签名,且数字签名是与消息相关联的,一旦消息被更改,数字签名也会失效
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
public class KeyPairGeneratorExample {
public static void main(String[] args) {
try {
// 使用RSA算法生成密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
// 生成密钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
System.out.println("公钥:" + keyPair.getPublic());
System.out.println("私钥:" + keyPair.getPrivate());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
在上述代码中,我们使用了RSA算法生成一个2048位的密钥对,其中KeyPairGenerator.getInstance("RSA")用于获取RSA算法的密钥对生成器,initialize(2048)用于设置密钥长度,generateKeyPair()用于生成密钥对。
接下来,我们使用私钥对数据进行加签
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
public class SignExample {
public static void main(String[] args) {
try {
// 使用RSA算法生成密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// 使用私钥对数据进行加签
String data = "Hello World!";
byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(keyPair.getPrivate());
signature.update(dataBytes);
byte[] signBytes = signature.sign();
System.out.println("数字签名:" + new String(signBytes, StandardCharsets.UTF_8));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
在上述代码中,我们使用了SHA256withRSA算法生成数字签名,其中Signature.getInstance("SHA256withRSA")用于获取SHA256withRSA算法的签名对象,initSign(keyPair.getPrivate())用于初始化签名对象并指定私钥,update(dataBytes)用于更新待加签的数据,sign()用于生成数字签名
5、验签
验签是指在数据接收端,使用相同的密钥和加密算法对数据进行解密并验证数字签名的过程。接收方收到原始报文和数字签名后,使用公钥对数字签名进行解密,如果能得到摘要信息,说明的确是持有与该公钥匹配的私钥的发送方发出的。然后,对收到的数据使用相同的哈希函数生成摘要,将得到的摘要结果与解密出来的摘要进行对比。如果两者一致,就证明数据未被修改过。这个过程称为验证数字签名,简称验签
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.PublicKey;
import java.security.Signature;
public class VerifyExample {
public static void main(String[] args) {
try {
// 假设这里已经有了签名数据和原始数据
String data = "Hello World!";
byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);
byte[] signBytes = /* 这里填入加签代码生成的签名数据 */;
// 获取公钥
PublicKey publicKey = /* 这里填入对应的公钥 */;
// 使用公钥对签名进行验签
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey);
signature.update(dataBytes);
boolean verified = signature.verify(signBytes);
if (verified) {
System.out.println("数字签名验证通过");
} else {
System.out.println("数字签名验证不通过");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
在验签代码中,需要填入加签代码生成的签名数据、对应的公钥,然后使用公钥对签名进行验证。如果验证通过,则说明数字签名有效;否则,说明数字签名无效。
为什么有了加密解密还需要加签验签?
假设A想向B发送一份重要的文件,并且希望确保文件在传输过程中没有被篡改。A可以对文件进行数字签名(加签),然后将文件和数字签名一起发送给B。B在接收到文件后,可以使用A的公钥对数字签名进行验证,以确认文件的完整性和真实性。
如果在传输过程中有攻击者E尝试篡改文件内容,即使E能够拦截并修改了文件,但由于E没有A的私钥无法伪造有效的数字签名。因此,B在验证数字签名时会发现签名无效,从而知道文件已被篡改。
通过加签验证,B可以确保接收到的文件是由A签署的原始文件,而不是经过篡改的文件。这样可以防止数据被篡改、伪造或否认,保证数据的安全性和可靠性。
因此,加签验证在数据传输和通信过程中起着非常重要的作用,是保障数据完整性和真实性的重要手段。
6、证书
在网络通信中,证书(Certificate)是用于验证通信双方身份的一种电子文档,通常由权威的第三方机构(称为证书颁发机构,CA)颁发。证书在保障网络通信的安全性和可信性方面起着至关重要的作用。
例如,当你访问一个HTTPS网站时,服务器会提供一个证书给浏览器,浏览器会验证该证书,确认服务器的身份是真实的,而不是假冒的
6.1证书的作用
验证公钥的真实性和可信性。
确认公钥持有者的身份
通过权威的第三方(证书颁发机构,CA)建立信任链。
6.2证书的组成
- 版本号:标识证书的版本。
- 序列号:唯一标识一个证书的编号。
- 签名算法:用于生成证书签名的算法。
- 发行者(Issuer):颁发证书的 CA 的名称。
- 有效期:证书的有效时间段。
- 主体(Subject):证书持有者的名称。
- 主体公钥信息:证书持有者的公钥及其算法信息。
- 扩展(Extensions):可选的扩展信息。
- 签名:由 CA 使用其私钥对证书内容进行签名。
6.3证书的工作原理
证书的工作原理基于公钥加密和数字签名技术,主要包括以下步骤
1. 证书申请:申请者生成一对公私钥,并将公钥和相关信息提交给 CA 进行证书申请。
2. 证书颁发:CA 对申请者的身份进行验证,验证通过后使用 CA 的私钥对申请者的公钥和相关信息进行签名,生成证书
3. 证书分发:申请者获得证书后,可以将证书分发给通信对象。
4. 证书验证:通信对象使用 CA 的公钥对证书进行验证,确保证书的真实性和完整性。
5. 安全通信:通信双方通过证书进行身份验证和数据加密,实现安全通信。