加密解密的學習與理解

數字摘要

MD5

Message Digest Algorithm MD5(消息摘要算法第五版),用于確保信息的完整一致。

MD5算法具有以下特點:

  1. 壓縮性:任意長度的數據,算出的MD5值長度都是固定的(128bit,32位十六進制)。
  2. 容易計算:從原數據計算出MD5值很容易。
  3. 抗修改性:對原數據進行任何改動,哪怕只修改1個字節,所得到的MD5值都有很大區別。
  4. 強抗碰撞:已知原數據和其MD5值,想找到一個具有相同MD5值的數據(即偽造數據)是非常困難的。

MD5作用:
確定數據未被修改,保證文件(數據)的唯一性

使用場景:
用戶的密碼一般都是需要進行md5加密。

注意:
MD5是不可逆的,而且1KB的文件和1TB的文件的MD5值的長度是一樣的。
SHA1
SHA1:160bit,40位十六進制

SHA1和MD5的算法不一樣,但是作用是一樣的,都是用來保證文件的唯一性。

Android中,androidsupport v4包的版本沖突,就是根據SHA1值來進行判斷的。

類似QQ、360的秒傳功能,其實也是根據文件的SHA1來判斷是否網盤已經有此正在發送的文件,若有,則無需用戶再次上傳。
加鹽
加鹽就是在密碼的前面加入一些特殊字符,如:%&&%& 。

場景:
用戶注冊,密碼111111 -> 對密碼進行MD5 -> 保存密碼的MD5值到數據庫
風險:
假如數據庫泄漏,現在網絡上有很多MD5在線解析平臺(其原理是將MD5值與一個龐大的數據庫進行比對,最終得到原值),破壞者可以輕松得知用戶的密碼,用戶信息遭到泄漏。

解決方案:
用戶注冊,密碼111111 ->對密碼加鹽(&% + 111111 + ~%)->對加鹽后的密碼進行MD5 -> 保存MD5值到數據庫

加鹽實際上就是在原值的基礎上隨機的添加一些佐料,密碼經過加鹽后再存儲到數據庫中,破壞者哪怕得到了數據庫里的MD5值,也無法還原出正確的用戶密碼,保證了用戶信息的安全性。
加密解密
Android中常見的加密解密
對稱加密算法
對稱加密算法指的是加密和解密操作只有一把密鑰,如果密鑰暴露,文件就會被暴露。

常見的對稱加密算法有:
l DES:Data Encryption Standard(數據加密標準)
l AES:Advanced Encryption Standard(高級加密標準),AES是在DES的基礎上發展而來的

對稱加密算法的特點:
l 加密速度比較快,可以加密比較大的文件
l 密碼可以自己指定
非對稱加密算法
非對稱的加密算法有兩把鑰匙(密鑰對),分別為公鑰和私鑰,公鑰可以給別人,私鑰需要自己保存。

常見加密:

RSA

加密解密方式:
一方用來加密,則另一方就用來解密,成對使用
l 公鑰加密 -> 私鑰解密
l 私鑰加密 -> 公鑰解密
數字簽名:
私鑰簽名-->公鑰校驗,其目的在于確定數據來源的不可否認性,確定數據的所屬關系

非對稱加密算法的特點:
l 加密速度比慢一些,但是安全系數比較高
l 秘鑰對需要程序生成,不能我們自己定義
加密解密實例

DES

工具類:

package com.billy.androidutils.utils.encrypt.des;

import java.io.IOException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import Decoder.BASE64Decoder;
import Decoder.BASE64Encoder;

public class Des {

    private final static String DES = "DES";

    public static void main(String[] args) throws Exception {
        String data = "大王蓋地虎";
        String key = "wang!@#$%";
        System.err.println(encrypt(data, key));
//    System.err.println(decrypt(encrypt(data, key), key));

    }

    /**
     * Description 根據鍵值進行加密
     * @param data
     * @param key  加密鍵byte數組
     * @return
     * @throws Exception
     */
    public static String encrypt(String data, String key) throws Exception {
        byte[] bt = encrypt(data.getBytes(), key.getBytes());
        String strs = new BASE64Encoder().encode(bt);
        return strs;
    }

    /**
     * Description 根據鍵值進行解密
     * @param data
     * @param key  加密鍵byte數組
     * @return
     * @throws IOException
     * @throws Exception
     */
    public static String decrypt(String data, String key) throws IOException, Exception {
        if (data == null)
            return null;
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] buf = decoder.decodeBuffer(data);
        byte[] bt = decrypt(buf, key.getBytes());
        return new String(bt);
    }

    /**
     * Description 根據鍵值進行加密
     * @param data
     * @param key  加密鍵byte數組
     * @return
     * @throws Exception
     */
    private static byte[] encrypt(byte[] data, byte[] key) throws Exception {
        // 生成一個可信任的隨機數源
        SecureRandom sr = new SecureRandom();

        // 從原始密鑰數據創建DESKeySpec對象
        DESKeySpec dks = new DESKeySpec(key);

        // 創建一個密鑰工廠,然后用它把DESKeySpec轉換成SecretKey對象
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey securekey = keyFactory.generateSecret(dks);

        // Cipher對象實際完成加密操作
        Cipher cipher = Cipher.getInstance(DES);

        // 用密鑰初始化Cipher對象
        cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);

        return cipher.doFinal(data);
    }

    /**
     * Description 根據鍵值進行解密
     * @param data
     * @param key  加密鍵byte數組
     * @return
     * @throws Exception
     */
    private static byte[] decrypt(byte[] data, byte[] key) throws Exception {
        // 生成一個可信任的隨機數源
        SecureRandom sr = new SecureRandom();

        // 從原始密鑰數據創建DESKeySpec對象
        DESKeySpec dks = new DESKeySpec(key);

        // 創建一個密鑰工廠,然后用它把DESKeySpec轉換成SecretKey對象
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey securekey = keyFactory.generateSecret(dks);

        // Cipher對象實際完成解密操作
        Cipher cipher = Cipher.getInstance(DES);

        // 用密鑰初始化Cipher對象
        cipher.init(Cipher.DECRYPT_MODE, securekey, sr);

        return cipher.doFinal(data);
    }
}

加密:

*/** 要被加密的數據 */*private String    data  = "需要加密的數據";*/**  秘鑰 */*private String    key      = "%^&*()^&*(^&";*/**DES加密的結果 */*private String    mDesEncryptResult;
……
//加密mDesEncryptResult=Des.*encrypt*(data, key);
……

解密:

//解密
mDesDecryptResult = Des.*decrypt*(mDesEncryptResult, key);

AES

工具類:

package com.billy.androidutils.utils.encrypt.aes;

import android.annotation.SuppressLint;

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES加密
 */
public class Aes {

    private final static String HEX = "0123456789ABCDEF";

    public static String encrypt(String data, String password) throws Exception {
        byte[] rawKey = getRawKey(password.getBytes());
        byte[] result = encrypt(rawKey, data.getBytes());
        return toHex(result);
    }

    public static String decrypt(String encrypted, String password) throws Exception {
        byte[] rawKey = getRawKey(password.getBytes());
        byte[] enc = toByte(encrypted);
        byte[] result = decrypt(rawKey, enc);
        return new String(result);
    }

    @SuppressLint("TrulyRandom")
    private static byte[] getRawKey(byte[] password) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
        sr.setSeed(password);
        kgen.init(128, sr); // 192 and 256 bits may not be available
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();
        return raw;
    }

    private static byte[] encrypt(byte[] raw, byte[] data) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
        byte[] encrypted = cipher.doFinal(data);
        return encrypted;
    }

    private static byte[] decrypt(byte[] raw, byte[] data) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
        byte[] decrypted = cipher.doFinal(data);
        return decrypted;
    }

    private static byte[] toByte(String hexString) {
        int len = hexString.length() / 2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++) {
            result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();
        }
        return result;
    }

    private static String toHex(byte[] buf) {
        if (buf == null) {
            return "";
        }
        StringBuffer result = new StringBuffer(2 * buf.length);
        for (int i = 0; i < buf.length; i++) {
            appendHex(result, buf[i]);
        }
        return result.toString();
    }

    private static void appendHex(StringBuffer sb, byte b) {
        sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
    }
}

加密:

*/** 要被加密的數據 */*
private String    data   = "需要加密的數據";
*/**  秘鑰 */*
private String  key  = "%^&*()^&*(^&";
*/** AES加密的結果 */*
private String    mAesEncryptResult;
……
// 加密mAesEncryptResult = Aes.*encrypt*(data,key);
……

解密:

// 解密String aesDecryptResult = Aes.*decrypt*(mAesEncryptResult,key);

RSA

在進行RSA加密解密之前,先要獲取RSA的密鑰對。不同于AES和DES,AES和DES的秘鑰只有一個,而且可以自己指定,但是RSA的密鑰對是代碼生成的,不能由我們來定義。

包含:
KeyGen:密鑰生成算法,PK,SK=KeyGen()Encrypt:加密算法,X=Encrypt(PK,M)Decrypt:解密算法,M=Decrypt(SK,X)Sign:簽名算法,sign= Sign(SK,M)。Verify:驗證算法,b= Verify(PK,sign,M)注:PK:公鑰。SK:密鑰。M:明文。X:密文。sign:明文的簽名
用途:
a:公鑰加密,私鑰解密。用于傳輸數據的加密。b: 私鑰簽名,公鑰驗簽。用于傳輸數據的完整性校驗。優點:加密解密使用不同的密鑰缺點:加密解密速度慢,資源消耗大

工具類:

package com.billy.androidutils.utils.encrypt.rsa;

import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

import Decoder.BASE64Decoder;
import Decoder.BASE64Encoder;

public class RSACrypt {

   /**
    * 文件讀取緩沖區大小
    */
   private static final int CACHE_SIZE = 1024;

   /**
    * <p>
    * BASE64字符串解碼為二進制數據
    * </p>
    *
    * @param base64
    * @return
    * @throws Exception
    */
   public static byte[] decode(String base64) throws Exception {
       return new BASE64Decoder().decodeBuffer(base64);
   }

   /**
    * <p>
    * 二進制數據編碼為BASE64字符串
    * </p>
    *
    * @param bytes
    * @return
    * @throws Exception
    */
   public static String encode(byte[] bytes) throws Exception {
       return new BASE64Encoder().encode(bytes);
   }

   /**
    * 加密算法RSA
    */
   // public static final String KEY_ALGORITHM = "RSA";

   public static final String KEY_ALGORITHM = "RSA";

   /**
    * 簽名算法
    */
   public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

   /**
    * 獲取公鑰的key
    */
   private static final String PUBLIC_KEY = "RSAPublicKey";

   /**
    * 獲取私鑰的key
    */
   private static final String PRIVATE_KEY = "RSAPrivateKey";

   /**
    * RSA最大加密明文大小
    */
   private static final int MAX_ENCRYPT_BLOCK = 117;

   /**
    * RSA最大解密密文大小
    */
   private static final int MAX_DECRYPT_BLOCK = 128;

   /**
    * <p>
    * 生成密鑰對(公鑰和私鑰)
    * </p>
    *
    * @return
    * @throws Exception
    */
   public static Map<String, Object> genKeyPair() throws Exception {
       KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
       keyPairGen.initialize(1024);
       KeyPair keyPair = keyPairGen.generateKeyPair();
       RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
       RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
       Map<String, Object> keyMap = new HashMap<String, Object>(2);
       keyMap.put(PUBLIC_KEY, publicKey);
       keyMap.put(PRIVATE_KEY, privateKey);
       return keyMap;
   }

   /**
    * <p>
    * 生成密鑰對(公鑰和私鑰)
    * </p>
    *
    * @return
    * @throws Exception
    */
   public static Map<String, Object> genKeyPair(String seed) throws Exception {
       KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
       keyPairGen.initialize(1024);
       // SecureRandom secrand = new SecureRandom();
       // secrand.setSeed(seed.getBytes()); // 初始化隨機產生器
       // keyPairGen.initialize(1024, secrand);
       KeyPair keyPair = keyPairGen.generateKeyPair();
       RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
       RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
       Map<String, Object> keyMap = new HashMap<String, Object>(2);
       keyMap.put(PUBLIC_KEY, publicKey);
       keyMap.put(PRIVATE_KEY, privateKey);
       return keyMap;
   }

   /**
    * <p>
    * 用私鑰對信息生成數字簽名
    * </p>
    *
    * @param data
    *            已加密數據
    * @param privateKey
    *            私鑰(BASE64編碼)
    *
    * @return
    * @throws Exception
    */
   public static String sign(byte[] data, String privateKey) throws Exception {
       byte[] keyBytes = decode(privateKey);
       PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
       KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
       PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
       Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
       signature.initSign(privateK);
       signature.update(data);
       return encode(signature.sign());
   }

   /**
    * <p>
    * 校驗數字簽名
    * </p>
    *
    * @param data
    *            已加密數據
    * @param publicKey
    *            公鑰(BASE64編碼)
    * @param sign
    *            數字簽名
    *
    * @return
    * @throws Exception
    *
    */
   public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
       byte[] keyBytes = decode(publicKey);
       X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
       KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

       PublicKey publicK = keyFactory.generatePublic(keySpec);
       Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
       signature.initVerify(publicK);
       signature.update(data);
       return signature.verify(decode(sign));
   }

   /**
    * <P>
    * 私鑰解密
    * </p>
    *
    * @param encryptedData
    *            已加密數據
    * @param privateKey
    *            私鑰(BASE64編碼)
    * @return
    * @throws Exception
    */
   public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception {
       byte[] keyBytes = decode(privateKey);
       PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
       KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
       Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
//     Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

       Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");

       cipher.init(Cipher.DECRYPT_MODE, privateK);
       int inputLen = encryptedData.length;
       ByteArrayOutputStream out = new ByteArrayOutputStream();
       int offSet = 0;
       byte[] cache;
       int i = 0;
       // 對數據分段解密
       while (inputLen - offSet > 0) {
           if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
               cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
           } else {
               cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
           }
           out.write(cache, 0, cache.length);
           i++;
           offSet = i * MAX_DECRYPT_BLOCK;
       }
       byte[] decryptedData = out.toByteArray();
       out.close();
       return decryptedData;
   }

   /**
    * <p>
    * 公鑰解密
    * </p>
    *
    * @param encryptedData
    *            已加密數據
    * @param publicKey
    *            公鑰(BASE64編碼)
    * @return
    * @throws Exception
    */
   public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception {
       byte[] keyBytes = decode(publicKey);
       X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
       KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
       Key publicK = keyFactory.generatePublic(x509KeySpec);
       // Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

       Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
       cipher.init(Cipher.DECRYPT_MODE, publicK);
       int inputLen = encryptedData.length;
       ByteArrayOutputStream out = new ByteArrayOutputStream();
       int offSet = 0;
       byte[] cache;
       int i = 0;
       // 對數據分段解密
       while (inputLen - offSet > 0) {
           if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
               cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
           } else {
               cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
           }
           out.write(cache, 0, cache.length);
           i++;
           offSet = i * MAX_DECRYPT_BLOCK;
       }
       byte[] decryptedData = out.toByteArray();
       out.close();
       return decryptedData;
   }

   /**
    * <p>
    * 公鑰加密
    * </p>
    *
    * @param data
    *            源數據
    * @param publicKey
    *            公鑰(BASE64編碼)
    * @return
    * @throws Exception
    */
   public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
       byte[] keyBytes = decode(publicKey);
       X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
       KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
       Key publicK = keyFactory.generatePublic(x509KeySpec);
       // 對數據加密
       // Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

       Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");

       cipher.init(Cipher.ENCRYPT_MODE, publicK);
       int inputLen = data.length;
       ByteArrayOutputStream out = new ByteArrayOutputStream();
       int offSet = 0;
       byte[] cache;
       int i = 0;
       // 對數據分段加密
       while (inputLen - offSet > 0) {
           if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
               cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
           } else {
               cache = cipher.doFinal(data, offSet, inputLen - offSet);
           }
           out.write(cache, 0, cache.length);
           i++;
           offSet = i * MAX_ENCRYPT_BLOCK;
       }
       byte[] encryptedData = out.toByteArray();
       out.close();
       return encryptedData;
   }

   /**
    * <p>
    * 私鑰加密
    * </p>
    *
    * @param data
    *            源數據
    * @param privateKey
    *            私鑰(BASE64編碼)
    * @return
    * @throws Exception
    */
   public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception {
       byte[] keyBytes = decode(privateKey);
       PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
       KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
       Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
       // Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
       Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
       cipher.init(Cipher.ENCRYPT_MODE, privateK);
       int inputLen = data.length;
       ByteArrayOutputStream out = new ByteArrayOutputStream();
       int offSet = 0;
       byte[] cache;
       int i = 0;
       // 對數據分段加密
       while (inputLen - offSet > 0) {
           if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
               cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
           } else {
               cache = cipher.doFinal(data, offSet, inputLen - offSet);
           }
           out.write(cache, 0, cache.length);
           i++;
           offSet = i * MAX_ENCRYPT_BLOCK;
       }
       byte[] encryptedData = out.toByteArray();
       out.close();
       return encryptedData;
   }

   /**
    * <p>
    * 獲取私鑰
    * </p>
    *
    * @param keyMap
    *            密鑰對
    * @return
    * @throws Exception
    */
   public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
       Key key = (Key) keyMap.get(PRIVATE_KEY);
       return encode(key.getEncoded());
   }

   /**
    * <p>
    * 獲取公鑰
    * </p>
    *
    * @param keyMap
    *            密鑰對
    * @return
    * @throws Exception
    */
   public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
       Key key = (Key) keyMap.get(PUBLIC_KEY);
       return encode(key.getEncoded());
   }

}

生成RSA密鑰對:

/** RSA加密的公鑰 */
private String mPublicKey;

/** RSA加密的私鑰 */
private String mPrivateKey;
……
/**
 *  生成RSA密鑰對
 */
private void generateKeyPair() {
    // 通過代碼生成rsa對應的公鑰和私鑰
    try {
        // 1.生成秘鑰對
        Map<String, Object> keyPair = RSACrypt.genKeyPair();
        // 2.得到公鑰
        mPublicKey = RSACrypt.getPublicKey(keyPair);
        // 3.得到私鑰
        mPrivateKey = RSACrypt.getPrivateKey(keyPair);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

加密:


/** RSA私鑰加密的結果 */
private byte[] mRsaEncryptByPrivateKeys;
……
// 加密
mRsaEncryptByPrivateKeys = RSACrypt.encryptByPrivateKey(data.getBytes(), mPrivateKey);
// 只能調用RSACrypt里面的方法把byte[]-->String
String rsaEncodeResult = RSACrypt.encode(mRsaEncryptByPrivateKeys);

解密:


// 解密
byte[] decryptByPublicKey = RSACrypt.decryptByPublicKey(mRsaEncryptByPrivateKeys, mPublicKey);
// 這里可以通過new String把byte[]-->String
String rsaDecodeResult = new String(decryptByPublicKey);

RSA公鑰互換
公鑰互換指的是兩個人或者兩個機構互相交換公鑰,換句話就是說兩個密鑰對的持有者相互的置換公鑰。

場景:
A機構有私鑰“A private key”和公鑰“A public key”;
B機構有私鑰“B private key”和“B public key”;
A機構和B機構互相置換了公鑰;
置換后A機構持有:“A private key”、“A public key”、“B public key”;
置換后B機構持有:“B private key”、“B public key”、“A public key”;

當A機構要向B機構發送數據的時候,可以用“A private key”或者“B public key”對數據進行加密,B機構就可以用”A public key”或者“B private key”對加密的數據進行解密了。

公鑰互換的作用:

  1. 加密解密
  2. 簽名校驗
    數字簽名
    數字簽名的作用就是確定數據來源的不可否認性,確定數據的所屬關系(其實就是確定privatekey在哪里)。

注意:
數字簽名只能用私鑰進行加密,用公鑰進行校驗

原理:
數字簽名必須用私鑰來做加密,那么校驗的時候就只能用公鑰。
而私鑰是由個人自己保存的,是不能告訴外界的,能告訴給外界的只有自己的公鑰。
因此,若一個加密的數據能夠被一個公鑰校驗,那么就可以唯一的確定這個加密數據的私鑰來自哪里。

public class Test {
  public static void main(String[] args) {
     try {
           // 生成密鑰對
        Map<String, Object> genKeyPair = RSACrypt.genKeyPair();
        String privateKey = RSACrypt.getPrivateKey(genKeyPair);
        String publicKey = RSACrypt.getPublicKey(genKeyPair);

        System.out.println("privateKey:\r\n" + privateKey);
        System.out.println("publicKey:\r\n" + publicKey);

        System.out.println("--------------開始簽名,驗證--------------");
           // 簽名前的源數據
        String str = "A同學向B同學了借了100w";
        String str1 = "ahhhhhhhha";

        // 開始對數據進行簽名
        byte[] data = str.getBytes();
        // 獲取簽名后的數據
        String sign = RSACrypt.sign(data, privateKey);
        System.out.println("sign\r\n:" + sign);

        // 對簽名的數據進行校驗
        // boolean verify = RSACrypt.verify(原始內容,公鑰, 簽名之后的內容);
        boolean verify = RSACrypt.verify(data, publicKey, sign);

        // 是否校驗成功
        if (verify) {
           System.out.println("verfiy成功,確實是a同學給我打的欠條");
        } else {
           System.out.println("verfiy不成功");
        } 
     } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
     } catch (Exception e) {
        e.printStackTrace();
     }
  }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,106評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,516評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內容