对称加密与非对称加密

Posted Linyb极客之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对称加密与非对称加密相关的知识,希望对你有一定的参考价值。

安全的交流方式需要同时满足下面三个条件

1.完整性,即消息没有中途篡改过。 2.保密性,第三方无法解密。 3.可认证性,消息的接收方可以确定消息是谁发送的。

对称加密

双方使用的同一个密钥,既可以加密又可以解密,这种加密方法称为对称加密,也称为单密钥加密。

优点:速度快,对称性加密通常在消息发送方需要加密大量数据时使用,算法公开、计算量小、加密速度快、加密效率高。

缺点:在数据传送前,发送方和接收方必须商定好秘钥,然后 使双方都能保存好秘钥。其次如果一方的秘钥被泄露,那么加密信息也就不安全了。另外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的唯一秘 钥,这会使得收、发双方所拥有的钥匙数量巨大,密钥管理成为双方的负担。

在对称加密算法中常用的算法有:DES、AES等。

AES:密钥的长度可以为128、192和256位,也就是16个字节、24个字节和32个字节

DES:密钥的长度64位,8个字节。

java中使用des加密解密

 
   
   
 
  1. import java.security.SecureRandom;

  2. import javax.crypto.Cipher;

  3. import javax.crypto.KeyGenerator;

  4. import javax.crypto.SecretKey;

  5. import javax.crypto.spec.SecretKeySpec;

  6. public class DESUtil {

  7.    public static final String DES = "DES";

  8.    public static final String charset = null; // 编码格式;默认null为GBK

  9.    public static final int keysizeDES = 0;

  10.    private static DESUtil instance;

  11.    private DESUtil() {

  12.    }

  13.    // 单例

  14.    public static DESUtil getInstance() {

  15.        if (instance == null) {

  16.            synchronized (MD5Util.class) {

  17.                if (instance == null) {

  18.                    instance = new DESUtil();

  19.                }

  20.            }

  21.        }

  22.        return instance;

  23.    }

  24.    /**

  25.     * 使用 DES 进行加密

  26.     */

  27.    public String encode(String res, String key) {

  28.        return keyGeneratorES(res, DES, key, keysizeDES, true);

  29.    }

  30.    /**

  31.     * 使用 DES 进行解密

  32.     */

  33.    public String decode(String res, String key) {

  34.        return keyGeneratorES(res, DES, key, keysizeDES, false);

  35.    }

  36.    // 使用KeyGenerator双向加密,DES/AES,注意这里转化为字符串的时候是将2进制转为16进制格式的字符串,不是直接转,因为会出错

  37.    private String keyGeneratorES(String res, String algorithm, String key, int keysize, boolean isEncode) {

  38.        try {

  39.            KeyGenerator kg = KeyGenerator.getInstance(algorithm);

  40.            if (keysize == 0) {

  41.                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);

  42.                kg.init(new SecureRandom(keyBytes));

  43.            } else if (key == null) {

  44.                kg.init(keysize);

  45.            } else {

  46.                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);

  47.                kg.init(keysize, new SecureRandom(keyBytes));

  48.            }

  49.            SecretKey sk = kg.generateKey();

  50.            SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm);

  51.            Cipher cipher = Cipher.getInstance(algorithm);

  52.            if (isEncode) {

  53.                cipher.init(Cipher.ENCRYPT_MODE, sks);

  54.                byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);

  55.                return parseByte2HexStr(cipher.doFinal(resBytes));

  56.            } else {

  57.                cipher.init(Cipher.DECRYPT_MODE, sks);

  58.                return new String(cipher.doFinal(parseHexStr2Byte(res)));

  59.            }

  60.        } catch (Exception e) {

  61.            e.printStackTrace();

  62.        }

  63.        return null;

  64.    }

  65.    // 将二进制转换成16进制

  66.    private String parseByte2HexStr(byte buf[]) {

  67.        StringBuffer sb = new StringBuffer();

  68.        for (int i = 0; i < buf.length; i++) {

  69.            String hex = Integer.toHexString(buf[i] & 0xFF);

  70.            if (hex.length() == 1) {

  71.                hex = '0' + hex;

  72.            }

  73.            sb.append(hex.toUpperCase());

  74.        }

  75.        return sb.toString();

  76.    }

  77.    // 将16进制转换为二进制

  78.    private byte[] parseHexStr2Byte(String hexStr) {

  79.        if (hexStr.length() < 1)

  80.            return null;

  81.        byte[] result = new byte[hexStr.length() / 2];

  82.        for (int i = 0; i < hexStr.length() / 2; i++) {

  83.            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);

  84.            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);

  85.            result[i] = (byte) (high * 16 + low);

  86.        }

  87.        return result;

  88.    }

  89. }

java中使用AES加密解密

 
   
   
 
  1. import java.security.SecureRandom;

  2. import javax.crypto.Cipher;

  3. import javax.crypto.KeyGenerator;

  4. import javax.crypto.SecretKey;

  5. import javax.crypto.spec.SecretKeySpec;

  6. public class AESUtil {

  7.    public static final String AES = "AES";

  8.    public static final String charset = null; // 编码格式;默认null为GBK

  9.    public static final int keysizeAES = 128;

  10.    private static AESUtil instance;

  11.    private AESUtil() {

  12.    }

  13.    // 单例

  14.    public static AESUtil getInstance() {

  15.        if (instance == null) {

  16.            synchronized (MD5Util.class) {

  17.                if (instance == null) {

  18.                    instance = new AESUtil();

  19.                }

  20.            }

  21.        }

  22.        return instance;

  23.    }

  24.    /**

  25.     * 使用 AES 进行加密

  26.     */

  27.    public String encode(String res, String key) {

  28.        return keyGeneratorES(res, AES, key, keysizeAES, true);

  29.    }

  30.    /**

  31.     * 使用 AES 进行解密

  32.     */

  33.    public String decode(String res, String key) {

  34.        return keyGeneratorES(res, AES, key, keysizeAES, false);

  35.    }

  36.    // 使用KeyGenerator双向加密,DES/AES,注意这里转化为字符串的时候是将2进制转为16进制格式的字符串,不是直接转,因为会出错

  37.    private String keyGeneratorES(String res, String algorithm, String key, int keysize, boolean isEncode) {

  38.        try {

  39.            KeyGenerator kg = KeyGenerator.getInstance(algorithm);

  40.            if (keysize == 0) {

  41.                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);

  42.                kg.init(new SecureRandom(keyBytes));

  43.            } else if (key == null) {

  44.                kg.init(keysize);

  45.            } else {

  46.                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);

  47.                kg.init(keysize, new SecureRandom(keyBytes));

  48.            }

  49.            SecretKey sk = kg.generateKey();

  50.            SecretKeySpec sks = new SecretKeySpec(sk.getEncoded(), algorithm);

  51.            Cipher cipher = Cipher.getInstance(algorithm);

  52.            if (isEncode) {

  53.                cipher.init(Cipher.ENCRYPT_MODE, sks);

  54.                byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);

  55.                return parseByte2HexStr(cipher.doFinal(resBytes));

  56.            } else {

  57.                cipher.init(Cipher.DECRYPT_MODE, sks);

  58.                return new String(cipher.doFinal(parseHexStr2Byte(res)));

  59.            }

  60.        } catch (Exception e) {

  61.            e.printStackTrace();

  62.        }

  63.        return null;

  64.    }

  65.    // 将二进制转换成16进制

  66.    private String parseByte2HexStr(byte buf[]) {

  67.        StringBuffer sb = new StringBuffer();

  68.        for (int i = 0; i < buf.length; i++) {

  69.            String hex = Integer.toHexString(buf[i] & 0xFF);

  70.            if (hex.length() == 1) {

  71.                hex = '0' + hex;

  72.            }

  73.            sb.append(hex.toUpperCase());

  74.        }

  75.        return sb.toString();

  76.    }

  77.    // 将16进制转换为二进制

  78.    private byte[] parseHexStr2Byte(String hexStr) {

  79.        if (hexStr.length() < 1)

  80.            return null;

  81.        byte[] result = new byte[hexStr.length() / 2];

  82.        for (int i = 0; i < hexStr.length() / 2; i++) {

  83.            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);

  84.            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);

  85.            result[i] = (byte) (high * 16 + low);

  86.        }

  87.        return result;

  88.    }

  89. }

非对称加密

一对密钥由公钥和私钥组成(可以使用很多对密钥)。私钥解密公钥加密数据,公钥解密私钥加密数据(私钥公钥可以互相加密解密)。 私钥只能由一方保管,不能外泄。公钥可以交给任何请求方。

在非对称加密算法中常用的算法有: RSA等

缺点:速度较慢

优点:安全

java中使用rsa加密解密

 
   
   
 
  1. import java.io.FileInputStream;

  2. import java.io.FileOutputStream;

  3. import java.io.ObjectInputStream;

  4. import java.io.ObjectOutputStream;

  5. import java.security.Key;

  6. import java.security.KeyPair;

  7. import java.security.KeyPairGenerator;

  8. import java.security.SecureRandom;

  9. import javax.crypto.Cipher;

  10. import sun.misc.BASE64Decoder;

  11. import sun.misc.BASE64Encoder;

  12. public class RSA_Encrypt {

  13.    /** 指定加密算法为DESede */

  14.    private static String ALGORITHM = "RSA";

  15.    /** 指定key的大小 */

  16.    private static int KEYSIZE = 1024;

  17.    /** 指定公钥存放文件 */

  18.    private static String PUBLIC_KEY_FILE = "PublicKey";

  19.    /** 指定私钥存放文件 */

  20.    private static String PRIVATE_KEY_FILE = "PrivateKey";

  21.    /**

  22.     * 生成密钥对

  23.     */

  24.    private static void generateKeyPair() throws Exception {

  25.        /** RSA算法要求有一个可信任的随机数源 */

  26.        SecureRandom sr = new SecureRandom();

  27.        /** 为RSA算法创建一个KeyPairGenerator对象 */

  28.        KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);

  29.        /** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */

  30.        kpg.initialize(KEYSIZE, sr);

  31.        /** 生成密匙对 */

  32.        KeyPair kp = kpg.generateKeyPair();

  33.        /** 得到公钥 */

  34.        Key publicKey = kp.getPublic();

  35.        /** 得到私钥 */

  36.        Key privateKey = kp.getPrivate();

  37.        /** 用对象流将生成的密钥写入文件 */

  38.        ObjectOutputStream oos1 = new ObjectOutputStream(new FileOutputStream(

  39.                PUBLIC_KEY_FILE));

  40.        ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream(

  41.                PRIVATE_KEY_FILE));

  42.        oos1.writeObject(publicKey);

  43.        oos2.writeObject(privateKey);

  44.        /** 清空缓存,关闭文件输出流 */

  45.        oos1.close();

  46.        oos2.close();

  47.    }

  48.    /**

  49.     * 加密方法 source: 源数据

  50.     */

  51.    public static String encrypt(String source) throws Exception {

  52.        generateKeyPair();

  53.        /** 将文件中的公钥对象读出 */

  54.        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(

  55.                PUBLIC_KEY_FILE));

  56.        Key key = (Key) ois.readObject();

  57.        ois.close();

  58.        /** 得到Cipher对象来实现对源数据的RSA加密 */

  59.        Cipher cipher = Cipher.getInstance(ALGORITHM);

  60.        cipher.init(Cipher.ENCRYPT_MODE, key);

  61.        byte[] b = source.getBytes();

  62.        /** 执行加密操作 */

  63.        byte[] b1 = cipher.doFinal(b);

  64.        BASE64Encoder encoder = new BASE64Encoder();

  65.        return encoder.encode(b1);

  66.    }

  67.    /**

  68.     * 解密算法 cryptograph:密文

  69.     */

  70.    public static String decrypt(String cryptograph) throws Exception {

  71.        /** 将文件中的私钥对象读出 */

  72.        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(

  73.                PRIVATE_KEY_FILE));

  74.        Key key = (Key) ois.readObject();

  75.        /** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */

  76.        Cipher cipher = Cipher.getInstance(ALGORITHM);

  77.        cipher.init(Cipher.DECRYPT_MODE, key);

  78.        BASE64Decoder decoder = new BASE64Decoder();

  79.        byte[] b1 = decoder.decodeBuffer(cryptograph);

  80.        /** 执行解密操作 */

  81.        byte[] b = cipher.doFinal(b1);

  82.        return new String(b);

  83.    }

  84.    public static void main(String[] args) throws Exception {

  85.        String source = "Hello World!";// 要加密的字符串

  86.        String cryptograph = encrypt(source);// 生成的密文

  87.        System.out.println(cryptograph);

  88.        System.out.println("=====================");

  89.        String target = decrypt(cryptograph);// 解密密文

  90.        System.out.println(target);

  91.    }

  92. }


消息摘要(散列运算,哈希运算)

对一段信息(Message)产生信息摘要(加密 Message-Digest),以防止被篡改。多次对同一个字符串加密结果一样,不可逆。

常用算法:md5,sha1

java中使用md5加密解密

 
   
   
 
  1. import java.security.MessageDigest;

  2. import javax.crypto.KeyGenerator;

  3. import javax.crypto.Mac;

  4. import javax.crypto.SecretKey;

  5. import javax.crypto.spec.SecretKeySpec;

  6. public class MD5Util {

  7.    public static final String MD5 = "MD5";

  8.    public static final String HmacMD5 = "HmacMD5";

  9.    public static final String charset = null; // 编码格式;默认null为GBK

  10.    private static MD5Util instance;

  11.    private MD5Util() {

  12.    }

  13.    // 单例

  14.    public static MD5Util getInstance() {

  15.        if (instance == null) {

  16.            synchronized (MD5Util.class) {

  17.                if (instance == null) {

  18.                    instance = new MD5Util();

  19.                }

  20.            }

  21.        }

  22.        return instance;

  23.    }

  24.    /**

  25.     * 使用 MD5 方法加密(无密码)

  26.     */

  27.    public String encode(String res) {

  28.        try {

  29.            MessageDigest md = MessageDigest.getInstance(MD5);

  30.            byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);

  31.            return BASE64Util.getInstance().encode(md.digest(resBytes).toString());

  32.        } catch (Exception e) {

  33.            e.printStackTrace();

  34.        }

  35.        return null;

  36.    }

  37.    /**

  38.     * 使用 MD5 方法加密(可以设密码)

  39.     */

  40.    public String encode(String res, String key) {

  41.        try {

  42.            SecretKey sk = null;

  43.            if (key == null) {

  44.                KeyGenerator kg = KeyGenerator.getInstance(HmacMD5);

  45.                sk = kg.generateKey();

  46.            } else {

  47.                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);

  48.                sk = new SecretKeySpec(keyBytes, HmacMD5);

  49.            }

  50.            Mac mac = Mac.getInstance(HmacMD5);

  51.            mac.init(sk);

  52.            byte[] result = mac.doFinal(res.getBytes());

  53.            return BASE64Util.getInstance().encode(result.toString());

  54.        } catch (Exception e) {

  55.            e.printStackTrace();

  56.        }

  57.        return null;

  58.    }

  59. }


java中使用sha1加密解密

 
   
   
 
  1. import java.security.MessageDigest;

  2. import javax.crypto.KeyGenerator;

  3. import javax.crypto.Mac;

  4. import javax.crypto.SecretKey;

  5. import javax.crypto.spec.SecretKeySpec;

  6. /**

  7. * 使用 SHA1 方法进行加密<br/>

  8. * SHA1方法加密是不可逆的,不能解密,要想解密就必须使用暴力解密<br/>

  9. * <p/>

  10. * 方法中的 res 参数:原始的数据<br/>

  11. * 方法中的 key 参数:密钥,可以随便写<br/>

  12. */

  13. public class SHA1Util {

  14.    public static final String SHA1 = "SHA1";

  15.    public static final String HmacSHA1 = "HmacSHA1";

  16.    public static final String charset = null; // 编码格式;默认null为GBK

  17.    private static SHA1Util instance;

  18.    private SHA1Util() {

  19.    }

  20.    // 单例

  21.    public static SHA1Util getInstance() {

  22.        if (instance == null) {

  23.            synchronized (SHA1Util.class) {

  24.                if (instance == null) {

  25.                    instance = new SHA1Util();

  26.                }

  27.            }

  28.        }

  29.        return instance;

  30.    }

  31.    /**

  32.     * 使用 SHA1 方法加密(无密码)

  33.     */

  34.    public String encode(String res) {

  35.        try {

  36.            MessageDigest md = MessageDigest.getInstance(SHA1);

  37.            byte[] resBytes = charset == null ? res.getBytes() : res.getBytes(charset);

  38.            return BASE64Util.getInstance().encode(md.digest(resBytes).toString());

  39.        } catch (Exception e) {

  40.            e.printStackTrace();

  41.        }

  42.        return null;

  43.    }

  44.    /**

  45.     * 使用 SHA1 方法加密(可以设密码)

  46.     */

  47.    public String encode(String res, String key) {

  48.        try {

  49.            SecretKey sk = null;

  50.            if (key == null) {

  51.                KeyGenerator kg = KeyGenerator.getInstance(HmacSHA1);

  52.                sk = kg.generateKey();

  53.            } else {

  54.                byte[] keyBytes = charset == null ? key.getBytes() : key.getBytes(charset);

  55.                sk = new SecretKeySpec(keyBytes, HmacSHA1);

  56.            }

  57.            Mac mac = Mac.getInstance(HmacSHA1);

  58.            mac.init(sk);

  59.            byte[] result = mac.doFinal(res.getBytes());

  60.            return BASE64Util.getInstance().encode(result.toString());

  61.        } catch (Exception e) {

  62.            e.printStackTrace();

  63.        }

  64.        return null;

  65.    }

  66. }


数字签名

1.对消息指定值进行md5等摘要运算,得到消息摘要。 2.使用发送方私钥对消息摘要进行加密(并不对消息本身加密) 3.接收方使用发送方公钥进行解密,计算哈希值。来判断消息是否一致。 注意:如果参数被截取到,消息本身还是看到的。

混合使用(非对称加密+数字签名)

首先接收方和发送方都有一对秘钥。 发送方: 1.对消息进行md5等摘要运算,得到消息摘要。 2.使用发送方私钥对消息摘要进行加密,该过程也称作签名。(确保了接收方能够确认自己的身份) 3.使用接收方的公钥对消息进行加密(确保了消息只能由期望的接收方解密) 4.发送消息和消息摘要 接收方: 1.使用发送发的公钥对消息摘要进行解密(确认了消息是由谁发送的),获得原始消息摘要 2.使用自己的私钥对消息进行解密(安全的获得了消息内容) 3.将消息进行散列运算,获得本地消息摘要。 4.将原始消息摘要与本地消息摘要对比(验签),确认消息是否被篡改。

缺点:比较耗时。



以上是关于对称加密与非对称加密的主要内容,如果未能解决你的问题,请参考以下文章

对称加密与非对称加密

对称加密与非对称加密算法

聊聊对称加密与非对称加密

对称加密与非对称加密各自的应用场景

对称加密与非对称加密

对称加密与非对称加密