互联网安全架构四(信息加密与秘钥管理)

目录

单向散列加密

MD5加密

在线MD5解密与加密

Java操作MD5加密

 

对称加密

常见的对称式加密技术

对称密码的优点

对称密码的缺点

对称密码案例

基于DES实现加密和解密

非对称加密

使用过程:

RSA 工具类

使用公钥加密和私钥解密案例

使用私钥加密和公钥解密案例



单向散列加密

散列是信息的提炼,通常其长度要比信息小得多,且为一个固定长度。加密性强的散列一定是不可逆的,这就意味着通过散列结果,无法推出任何部分的原始信息。任何输入信息的变化,哪怕仅一位,都将导致散列结果的明显变化,这称之为雪崩效应。散列还应该是防冲突的,即找不出具有相同散列结果的两条信息。具有这些特性的散列结果就可以用于验证信息是否被修改。
单向散列函数一般用于产生消息摘要,密钥加密等,常见的有:
1、MD5(Message Digest Algorithm 5):是RSA数据安全公司开发的一种单向散列算法,非可逆,相同的明文产生相同的密文。
2、SHA(Secure Hash Algorithm):可以对任意长度的数据运算生成一个160位的数值;
SHA-1与MD5的比较
因为二者均由MD4导出,SHA-1和MD5彼此很相似。相应的,他们的强度和其他特性也是相似,但还有以下几点不同:
1、对强行供给的安全性:最显著和最重要的区别是SHA-1摘要比MD5摘要长32 位。使用强行技术,产生任何一个报文使其摘要等于给定报摘要的难度对MD5是2128数量级的操作,而对SHA-1则是2160数量级的操作。这样,SHA-1对强行攻击有更大的强度。
2、对密码分析的安全性:由于MD5的设计,易受密码分析的攻击,SHA-1显得不易受这样的攻击。
3、速度:在相同的硬件上,SHA-1的运行速度比MD5慢。

1、特征:雪崩效应、定长输出和不可逆。
2、作用是:确保数据的完整性。
3、加密算法:md5(标准密钥长度128位)、sha1(标准密钥长度160位)、md4、CRC-32
4、加密工具:md5sum、sha1sum、openssl dgst。
5、计算某个文件的hash值,例如:md5sum/shalsum FileName,openssl dgst –md5/-sha

 

MD5加密

 

在线MD5解密与加密

http://www.cmd5.com/

 

Java操作MD5加密

MD5加盐实现方式

一般使用的加盐:

md5(Password+UserName),即将用户名和密码字符串相加再MD5,这样的MD5摘要基本上不可反查。

但有时候用户名可能会发生变化,发生变化后密码即不可用了(验证密码实际上就是再次计算摘要的过程)。

----------

因此我们做了一个非常简单的加盐算法,每次保存密码到数据库时,都生成一个随机16位数字,将这16位数字和密码相加再求MD5摘要,然后在摘要中再将这16位数字按规则掺入形成一个48位的字符串。

在验证密码时再从48位字符串中按规则提取16位数字,和用户输入的密码相加再MD5。按照这种方法形成的结果肯定是不可直接反查的,且同一个密码每次保存时形成的摘要也都是不同的。

代码如下:

 

/**

 * MD5加盐加密

 */

public class PasswordUtil {

      /**

       * 生成含有随机盐的密码

       */

      public static String generate(String password) {

            Random r = new Random();

            StringBuilder sb = new StringBuilder(16);

            sb.append(r.nextInt(99999999)).append(r.nextInt(99999999));

            int len = sb.length();

            if (len < 16) {

                  for (int i = 0; i < 16 - len; i++) {

                       sb.append("0");

                  }

            }

            String salt = sb.toString();

            password = md5Hex(password + salt);

            char[] cs = new char[48];

            for (int i = 0; i < 48; i += 3) {

                  cs[i] = password.charAt(i / 3 * 2);

                  char c = salt.charAt(i / 3);

                  cs[i + 1] = c;

                  cs[i + 2] = password.charAt(i / 3 * 2 + 1);

            }

            return new String(cs);

      }



      /**

       * 校验密码是否正确

       */

      public static boolean verify(String password, String md5) {

            char[] cs1 = new char[32];

            char[] cs2 = new char[16];

            for (int i = 0; i < 48; i += 3) {

                  cs1[i / 3 * 2] = md5.charAt(i);

                  cs1[i / 3 * 2 + 1] = md5.charAt(i + 2);

                  cs2[i / 3] = md5.charAt(i + 1);

            }

            String salt = new String(cs2);

            return md5Hex(password + salt).equals(new String(cs1));

      }



      /**

       * 获取十六进制字符串形式的MD5摘要

       */

      public static String md5Hex(String src) {

            try {

                  MessageDigest md5 = MessageDigest.getInstance("MD5");

                  byte[] bs = md5.digest(src.getBytes());

                  return new String(new Hex().encode(bs));

            } catch (Exception e) {

                  return null;

            }

      }



      public static void main(String[] args) {

            // 加密+加盐

            String password1 = generate("admin");

            System.out.println("结果:" + password1 + "   长度:" + password1.length());

            // 解码

            System.out.println(verify("admin", password1));

            // 加密+加盐

            String password2 = generate("admin");

            System.out.println("结果:" + password2 + "   长度:" + password2.length());

            // 解码

            System.out.println(verify("admin", password2));

      }

}

 

 

 

 

 

对称加密

 

对称密码技术:发件人和收件人使用其共同拥有的单个密钥 ,这种密钥既用于加密,也用于解密,叫做机密密钥(也称为对称密钥或会话密钥)。

    能够提供信息机密性(没有密钥信息不能被解密)、完整性(被改变的信息不能被解密)的服务。

    对称式密码学又称:单钥密码学、秘密密钥密码学、会话密钥密码学、私钥密码学、共享秘钥密码学

 

常见的对称式加密技术

  DES:(数据加密标准):分组式加密,算法源于Lucifer,作为NIST对称式加密标准;64位(有效位56位、校验8位),分组算法

  3DES:128位,分组算法

  IDEA(国际数据加密算法):128位,比DES快,分组算法

  Blowfish:32-448位,算法公开,分组算法

    RC4:流密码,密钥长度可变

    RC5:分组密码,密钥长度可变,最大2048位

    Rijndael:128位/196位/256位

    AES(高级加密标准):DES升级版,算法出自Rinjindael

对称密码的优点

 用户只需记忆一个密钥,就可用于加密、解密;

 与非对称加密方法相比,加密解密的计算量小,速度快,简单易用,适合于对海量数据进行加密处理

对称密码的缺点

如果密钥交换不安全,密钥的安全性就会丧失。特别是在电子商务环境下,当客户是未知的、不可信的实体时,如何使客户安全地获得密钥就成为一大难题。

    如果用户较多情况下的密钥管理问题。N*(N-1)/2

    如果密钥多个用户被共享,不能提供抗抵赖性

对称密码案例

 假设AliceBob是认识的,两人为了保证通信消息不被其它人截取,预先约定了一个密码,用来加密在他们之间传送的消息,这样即使有人截取了消息没有密码也无法知道消息的内容。由此便实现了机密性。

 

 

基于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 = "yigeyouzi";

            // 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));

      }



}

非对称加密

 使用一对密钥:一个用于加密信息,另一个则用于解密信息。

    两个密钥之间存在着相互依存关系:即用其中任一个密钥加密的信息只能用另一个密钥进行解密。

    其中加密密钥不同于解密密钥,公钥加密私钥解密,反之也可私钥加密公钥解密。

    密钥依据性质划分,将其中的一个向外界公开,称为公钥;另一个则自己保留,称为私钥。公钥(Public key)常用于数据加密(用对方公钥加密)或签名验证(用对方公钥解密),私钥(Private key)常用于数据解密(发送方用接收方公钥加密)或数字签名(用自己私钥加密)。

    机密性、完整性、抗抵赖性

使用过程:

乙方生成两把密钥(公钥和私钥)

甲方获取乙方的公钥,然后用它对信息加密。

乙方得到加密后的信息,用私钥解密,乙方也可用私钥加密字符串

甲方获取乙方私钥加密数据,用公钥解密

优点:难破解

缺点: 加密速度慢

常用算法:

RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)

 

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 = "yigeyouzi";

            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 = "yigeyouzi";

            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);

 

 

猜你喜欢

转载自blog.csdn.net/wota5037/article/details/111384113
今日推荐