1. 对称加密
对称密码技术:发件人和收件人使用其共同拥有的单个密钥 ,这种密钥既用于加密,也用于解密,叫做机密密钥(也称为对称密钥或会话密钥)。
能够提供信息机密性(没有密钥信息不能被解密)、完整性(被改变的信息不能被解密)的服务。
对称式密码学又称:单钥密码学、秘密密钥密码学、会话密钥密码学、私钥密码学、共享秘钥密码学。
1.1 常见的对称式加密技术
- DES(数据加密标准):分组式加密,算法源于Lucifer,作为NIST对称式加密标准;64位(有效位56位、校验8位),分组算法
- 3DES:128位,分组算法
- IDEA(国际数据加密算法):128位,比DES快,分组算法
- Blowfish:32-448位,算法公开,分组算法
- RC4:流密码,密钥长度可变
- RC5:分组密码,密钥长度可变,最大2048位
- Rijndael:128位/196位/256位
- AES(高级加密标准):DES升级版,算法出自Rinjindael
1.2 对称密码的优点
- 用户只需记忆一个密钥,就可用于加密、解密;
- 与非对称加密方法相比,加密解密的计算量小,速度快,简单易用,适合于对海量数据进行加密处理 。
1.3 对称密码的缺点
- 如果密钥交换不安全,密钥的安全性就会丧失。特别是在电子商务环境下,当客户是未知的、不可信的实体时,如何使客户安全地获得密钥就成为一大难题。
- 如果用户较多情况下的密钥管理问题 N*(N-1)/2
- 如果密钥多个用户被共享,不能提供抗抵赖性
1.4 对称密码案例
假设Alice和Bob是认识的,两人为了保证通信消息不被其它人截取,预先约定了一个密码,用来加密在他们之间传送的消息,这样即使有人截取了消息没有密码也无法知道消息的内容。由此便实现了机密性。
1.5 基于DES实现加密和解密
DES加密工具类:
/** * DES加密介绍 DES是一种对称加密算法,所谓对称加密算法即:加密和解密使用相同密钥的算法。DES加密算法出自IBM的研究, * 后来被美国政府正式采用,之后开始广泛流传,但是近些年使用越来越少,因为DES使用56位密钥,以现代计算能力, 24小时内即可被破解。虽然如此,在某些简单应用中,我们还是可以使用DES加密算法,本文简单讲解DES的JAVA实现 。 * 注意:DES加密和解密过程中,密钥长度都必须是8的倍数 */ public class DES { public DES() { } // 测试 public static void main(String args[]) { // 待加密内容 String str = "cryptology"; // 密码,长度要是8的倍数 String password = "95880288"; byte[] result = DES.encrypt(str.getBytes(), password); System.out.println("加密后:" + new String(result)); // 直接将如上内容解密 try { byte[] decryResult = DES.decrypt(result, password); System.out.println("解密后:" + new String(decryResult)); } catch (Exception e1) { e1.printStackTrace(); } } /** * 加密 * * @param datasource * byte[] * @param password * String * @return byte[] */ public static byte[] encrypt(byte[] datasource, String password) { try { SecureRandom random = new SecureRandom(); DESKeySpec desKey = new DESKeySpec(password.getBytes()); // 创建一个密匙工厂,然后用它把DESKeySpec转换成 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); SecretKey securekey = keyFactory.generateSecret(desKey); // Cipher对象实际完成加密操作 Cipher cipher = Cipher.getInstance("DES"); // 用密匙初始化Cipher对象,ENCRYPT_MODE用于将 Cipher 初始化为加密模式的常量 cipher.init(Cipher.ENCRYPT_MODE, securekey, random); // 现在,获取数据并加密 // 正式执行加密操作 return cipher.doFinal(datasource); // 按单部分操作加密或解密数据,或者结束一个多部分操作 } catch (Throwable e) { e.printStackTrace(); } return null; } /** * 解密 * * @param src * byte[] * @param password * String * @return byte[] * @throws Exception */ public static byte[] decrypt(byte[] src, String password) throws Exception { // DES算法要求有一个可信任的随机数源 SecureRandom random = new SecureRandom(); // 创建一个DESKeySpec对象 DESKeySpec desKey = new DESKeySpec(password.getBytes()); // 创建一个密匙工厂 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");// 返回实现指定转换的 // Cipher // 对象 // 将DESKeySpec对象转换成SecretKey对象 SecretKey securekey = keyFactory.generateSecret(desKey); // Cipher对象实际完成解密操作 Cipher cipher = Cipher.getInstance("DES"); // 用密匙初始化Cipher对象 cipher.init(Cipher.DECRYPT_MODE, securekey, random); // 真正开始解密操作 return cipher.doFinal(src); } }
DES加解密案例:
public class Demo01 { // 1.配置密钥 private static String PASSWORD = "95880288"; public static void main(String[] args) throws Exception { // 2.需要加密的内容 String content = "xxx"; // 3.使用DES 加密 byte[] encryptContent = DES.encrypt(content.getBytes(), PASSWORD); System.out.println("加密后内容:" + new String(encryptContent)); // 4.使用DES 解密 byte[] decrypt = DES.decrypt(encryptContent, PASSWORD); System.out.println("解密后内容:" + new String(decrypt)); } }
2. 非对称加密
- 使用一对密钥:一个用于加密信息,另一个则用于解密信息。
- 两个密钥之间存在着相互依存关系:即用其中任一个密钥加密的信息只能用另一个密钥进行解密。
- 其中加密密钥不同于解密密钥,公钥加密私钥解密,反之也可私钥加密公钥解密。
- 密钥依据性质划分,将其中的一个向外界公开,称为公钥;另一个则自己保留,称为私钥。
- 公钥(Public key)常用于数据加密(用对方公钥加密)或签名验证(用对方公钥解密),私钥(Private key)常用于数据解密(发送方用接收方公钥加密)或数字签名(用自己私钥加密)。
优点:机密性、完整性、抗抵赖性
举个例子:
使用过程:
- 乙方生成两把密钥(公钥和私钥)
- 甲方获取乙方的公钥,然后用它对信息加密。
- 乙方得到加密后的信息,用私钥解密,乙方也可用私钥加密字符串
- 甲方获取乙方私钥加密数据,用公钥解密
优缺点:优点难破解,缺点加密速度慢。
常用算法: RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)
3. 代码实现
先写RSA 工具类:
/** * RSA加解密工具类 * */ public class RSAUtil { public static String publicKey; // 公钥 public static String privateKey; // 私钥 /** * 生成公钥和私钥 */ public static void generateKey() { // 1.初始化秘钥 KeyPairGenerator keyPairGenerator; try { keyPairGenerator = KeyPairGenerator.getInstance("RSA"); SecureRandom sr = new SecureRandom(); // 随机数生成器 keyPairGenerator.initialize(512, sr); // 设置512位长的秘钥 KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 开始创建 RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate(); // 进行转码 publicKey = Base64.encodeBase64String(rsaPublicKey.getEncoded()); // 进行转码 privateKey = Base64.encodeBase64String(rsaPrivateKey.getEncoded()); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 私钥匙加密或解密 * * @param content * @param privateKeyStr * @return */ public static String encryptByprivateKey(String content, String privateKeyStr, int opmode) { // 私钥要用PKCS8进行处理 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyStr)); KeyFactory keyFactory; PrivateKey privateKey; Cipher cipher; byte[] result; String text = null; try { keyFactory = KeyFactory.getInstance("RSA"); // 还原Key对象 privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); cipher = Cipher.getInstance("RSA"); cipher.init(opmode, privateKey); if (opmode == Cipher.ENCRYPT_MODE) { // 加密 result = cipher.doFinal(content.getBytes()); text = Base64.encodeBase64String(result); } else if (opmode == Cipher.DECRYPT_MODE) { // 解密 result = cipher.doFinal(Base64.decodeBase64(content)); text = new String(result, "UTF-8"); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return text; } /** * 公钥匙加密或解密 * * @param content * @param privateKeyStr * @return */ public static String encryptByPublicKey(String content, String publicKeyStr, int opmode) { // 公钥要用X509进行处理 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyStr)); KeyFactory keyFactory; PublicKey publicKey; Cipher cipher; byte[] result; String text = null; try { keyFactory = KeyFactory.getInstance("RSA"); // 还原Key对象 publicKey = keyFactory.generatePublic(x509EncodedKeySpec); cipher = Cipher.getInstance("RSA"); cipher.init(opmode, publicKey); if (opmode == Cipher.ENCRYPT_MODE) { // 加密 result = cipher.doFinal(content.getBytes()); text = Base64.encodeBase64String(result); } else if (opmode == Cipher.DECRYPT_MODE) { // 解密 result = cipher.doFinal(Base64.decodeBase64(content)); text = new String(result, "UTF-8"); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return text; } // 测试方法 public static void main(String[] args) { /** * 注意: 私钥加密必须公钥解密 公钥加密必须私钥解密 */ System.out.println("-------------生成两对秘钥,分别发送方和接收方保管-------------"); RSAUtil.generateKey(); System.out.println("公钥匙给接收方:" + RSAUtil.publicKey); System.out.println("私钥给发送方:" + RSAUtil.privateKey); System.out.println("-------------第一个栗子,私钥加密公钥解密-------------"); // String textsr = "早啊,你吃早饭了吗?O(∩_∩)O~"; // // 私钥加密 // String cipherText = RSAUtil.encryptByprivateKey(textsr, // RSAUtil.privateKey, Cipher.ENCRYPT_MODE); // System.out.println("发送方用私钥加密后:" + cipherText); // // 公钥解密 // String text = RSAUtil.encryptByPublicKey(cipherText, // RSAUtil.publicKey, Cipher.DECRYPT_MODE); // System.out.println("接收方用公钥解密后:" + text); System.out.println("-------------第二个栗子,公钥加密私钥解密-------------"); // 公钥加密 String textsr = "吃过啦!你吃了吗?O(∩_∩)O~"; String cipherText = RSAUtil.encryptByPublicKey(textsr, RSAUtil.publicKey, Cipher.ENCRYPT_MODE); System.out.println("接收方用公钥加密后:" + cipherText); // 私钥解密 String text = RSAUtil.encryptByprivateKey(cipherText, RSAUtil.privateKey, Cipher.DECRYPT_MODE); System.out.print("发送方用私钥解密后:" + text); } }
使用公钥加密和私钥解密案例
public static void main(String[] args) { // 1. 生成(公钥和私钥)密钥对 RSAUtil.generateKey(); System.out.println("公钥:" + RSAUtil.publicKey); System.out.println("私钥:" + RSAUtil.privateKey); System.out.println("----------公钥加密私钥解密-------------"); // 使用 公钥加密,私钥解密 String textsr = "张三"; String encryptByPublic = RSAUtil.encryptByPublicKey(textsr, RSAUtil.publicKey, Cipher.ENCRYPT_MODE); System.out.println("公钥加密:" + encryptByPublic); String text = RSAUtil.encryptByprivateKey(encryptByPublic, RSAUtil.privateKey, Cipher.DECRYPT_MODE); System.out.print("私钥解密:" + text); }
使用私钥加密和公钥解密案例:
// 1. 生成(公钥和私钥)密钥对 RSAUtil.generateKey(); System.out.println("公钥:" + RSAUtil.publicKey); System.out.println("私钥:" + RSAUtil.privateKey); System.out.println("----------私加密公钥解密-------------"); // 使用 私加密,公钥解密 String textsr = "yushengjun"; String encryptByprivate = RSAUtil.encryptByprivateKey(textsr, RSAUtil.privateKey, Cipher.ENCRYPT_MODE); System.out.println("私钥加密后:" + encryptByprivate); String encryptByPublic = RSAUtil.encryptByPublicKey(encryptByprivate, RSAUtil.publicKey, Cipher.DECRYPT_MODE); System.out.println("公钥解密后:" + encryptByPublic);