1. 程式人生 > >對稱加密/非對稱加密/簽名演算法

對稱加密/非對稱加密/簽名演算法

對稱加密:

對稱加密是指,加密方和解密方使用同樣的祕鑰來進行加密和解密。

常用對稱加密:

1. DES演算法

DES演算法的入口引數有三個:Key、Data、Mode。其中Key為8個位元組共64位,是DES演算法的工作金鑰;Data也為8個位元組64位,是要被加密或被解密的資料;Mode為DES的工作方式,有兩種:加密或解密。DES演算法是這樣工作的:如Mode為加密,則用Key 去把資料Data進行加密, 生成Data的密碼形式(64位)作為DES的輸出結果;如Mode為解密,則用Key去把密碼形式的資料Data解密,還原為Data的明碼形式(64位)作為DES的輸出結果。DES演算法具有極高安全性,到目前為止,除了用窮舉搜尋法對DES演算法進行攻擊外,還沒有發現更有效的辦法。

java實現:

package com.xxx.controller.api;


import java.security.SecureRandom;

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

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class Test {

    /**
     * 入口函式
     * @param args
     */
    public static void main(String[] args) throws Exception{
        String test = desEncrypt("helloworld", "123456asdsadad");
        System.out.println("加密後:" + test);
        String data = desDecrypt(test, "123456asdsadad");
        System.out.println("解密後:" + data);
    }

    /**
     * DES加密演算法-加密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static String desEncrypt(String data, String key) throws Exception {
        SecureRandom sr = new SecureRandom(); //強隨機數
        DESKeySpec dks = new DESKeySpec(key.getBytes("UTF-8"));
        //金鑰工廠用來將金鑰(型別 Key 的不透明加密金鑰)轉換為金鑰規範(底層金鑰材料的透明表示形式)
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey securekey = keyFactory.generateSecret(dks);
        //DES加密
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); //DES演算法
        cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
        byte[] bt =  cipher.doFinal(data.getBytes());
        return new BASE64Encoder().encode(bt); //base64處理     
    }
    
    /**
     * DES加密演算法-解密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static String desDecrypt(String data, String key) throws Exception {
        byte[] buf = new BASE64Decoder().decodeBuffer(data); //base64處理     
        
        //強隨機數
        SecureRandom sr = new SecureRandom(); 
        
        //金鑰工廠用來將金鑰(型別 Key 的不透明加密金鑰)轉換為金鑰規範(底層金鑰材料的透明表示形式)
        DESKeySpec dks = new DESKeySpec(key.getBytes("UTF-8"));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        SecretKey securekey = keyFactory.generateSecret(dks);
        
        //DES解密
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); //DES演算法
        cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
        byte[] bt =  cipher.doFinal(buf);
        return new String(bt); 
    }

}


2. AES演算法

AES 是一個迭代的、對稱金鑰分組的密碼,它可以使用128、192 和 256 位金鑰,並且用 128 位(16位元組)分組加密和解密資料。與公共金鑰密碼使用金鑰對不同,對稱金鑰密碼使用相同的金鑰加密和解密資料。通過分組密碼返回的加密資料的位數與輸入資料相同。迭代加密使用一個迴圈結構,在該迴圈中重複置換和替換輸入資料。

java實現:

package com.xxx.controller;


import java.security.SecureRandom;

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

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class test {

    /**
     * 入口函式
     * @param args
     */
    public static void main(String[] args) throws Exception {
        String test = aesEncrypt("helloworld", "123456asdsadad");
        System.out.println("加密後:" + test);
        String data = aesDecrypt(test, "123456asdsadad");
        System.out.println("解密後:" + data);
    }

    /**
     * AES加密演算法-加密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static String aesEncrypt(String data, String key) throws Exception {
        //構造祕鑰生成器
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128, new SecureRandom(key.getBytes()));
        //產生原始對稱金鑰
        SecretKey secretKey = kgen.generateKey();
        byte[] enCodeFormat = secretKey.getEncoded();
        //生成金鑰
        SecretKeySpec keySpec = new SecretKeySpec(enCodeFormat, "AES");
        //AES加密演算法
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        byte[] byteContent = data.getBytes("utf-8");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        byte[] result = cipher.doFinal(byteContent);
        //base64處理
        return new BASE64Encoder().encode(result);
    }

    /**
     * AES加密演算法-解密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static String aesDecrypt(String data, String key) throws Exception {
        byte[] buf = new BASE64Decoder().decodeBuffer(data); //base64處理     

        //構造祕鑰生成器
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128, new SecureRandom(key.getBytes()));
        //產生原始對稱金鑰
        SecretKey secretKey = kgen.generateKey();
        byte[] enCodeFormat = secretKey.getEncoded();
        //生成金鑰
        SecretKeySpec keySpec = new SecretKeySpec(enCodeFormat, "AES");
        //AES加密演算法
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        byte[] result = cipher.doFinal(buf);
        //base64處理
        return new String(result);
    }

}


常用非對稱加密:

非對稱加密演算法實現機密資訊交換的基本過程是:甲方生成一對金鑰並將其中的一把作為公用金鑰向其它方公開;得到該公用金鑰的乙方使用該金鑰對機密資訊進行加密後再發送給甲方;甲方再用自己儲存的另一把專用金鑰對加密後的資訊進行解密。甲方只能用其專用金鑰解密由其公用金鑰加密後的任何資訊。


1. RSA演算法

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;

/**
 * RSA安全編碼元件
 * 
 * @author 樑棟
 * @version 1.0
 * @since 1.0
 */
public abstract class RSACoder extends Coder {
	public static final String KEY_ALGORITHM = "RSA";
	public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

	private static final String PUBLIC_KEY = "RSAPublicKey";
	private static final String PRIVATE_KEY = "RSAPrivateKey";

	/**
	 * 用私鑰對資訊生成數字簽名
	 * 
	 * @param data
	 *            加密資料
	 * @param privateKey
	 *            私鑰
	 * 
	 * @return
	 * @throws Exception
	 */
	public static String sign(byte[] data, String privateKey) throws Exception {
		// 解密由base64編碼的私鑰
		byte[] keyBytes = decryptBASE64(privateKey);

		// 構造PKCS8EncodedKeySpec物件
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

		// KEY_ALGORITHM 指定的加密演算法
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

		// 取私鑰匙物件
		PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);

		// 用私鑰對資訊生成數字簽名
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initSign(priKey);
		signature.update(data);

		return encryptBASE64(signature.sign());
	}

	/**
	 * 校驗數字簽名
	 * 
	 * @param data
	 *            加密資料
	 * @param publicKey
	 *            公鑰
	 * @param sign
	 *            數字簽名
	 * 
	 * @return 校驗成功返回true 失敗返回false
	 * @throws Exception
	 * 
	 */
	public static boolean verify(byte[] data, String publicKey, String sign)
			throws Exception {

		// 解密由base64編碼的公鑰
		byte[] keyBytes = decryptBASE64(publicKey);

		// 構造X509EncodedKeySpec物件
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

		// KEY_ALGORITHM 指定的加密演算法
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

		// 取公鑰匙物件
		PublicKey pubKey = keyFactory.generatePublic(keySpec);

		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		signature.initVerify(pubKey);
		signature.update(data);

		// 驗證簽名是否正常
		return signature.verify(decryptBASE64(sign));
	}

	/**
	 * 解密<br>
	 * 用私鑰解密
	 * 
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] decryptByPrivateKey(byte[] data, String key)
			throws Exception {
		// 對金鑰解密
		byte[] keyBytes = decryptBASE64(key);

		// 取得私鑰
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);

		// 對資料解密
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.DECRYPT_MODE, privateKey);

		return cipher.doFinal(data);
	}

	/**
	 * 解密<br>
	 * 用公鑰解密
	 * 
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] decryptByPublicKey(byte[] data, String key)
			throws Exception {
		// 對金鑰解密
		byte[] keyBytes = decryptBASE64(key);

		// 取得公鑰
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		Key publicKey = keyFactory.generatePublic(x509KeySpec);

		// 對資料解密
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.DECRYPT_MODE, publicKey);

		return cipher.doFinal(data);
	}

	/**
	 * 加密<br>
	 * 用公鑰加密
	 * 
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptByPublicKey(byte[] data, String key)
			throws Exception {
		// 對公鑰解密
		byte[] keyBytes = decryptBASE64(key);

		// 取得公鑰
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		Key publicKey = keyFactory.generatePublic(x509KeySpec);

		// 對資料加密
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);

		return cipher.doFinal(data);
	}

	/**
	 * 加密<br>
	 * 用私鑰加密
	 * 
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptByPrivateKey(byte[] data, String key)
			throws Exception {
		// 對金鑰解密
		byte[] keyBytes = decryptBASE64(key);

		// 取得私鑰
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);

		// 對資料加密
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.ENCRYPT_MODE, privateKey);

		return cipher.doFinal(data);
	}

	/**
	 * 取得私鑰
	 * 
	 * @param keyMap
	 * @return
	 * @throws Exception
	 */
	public static String getPrivateKey(Map<String, Object> keyMap)
			throws Exception {
		Key key = (Key) keyMap.get(PRIVATE_KEY);

		return encryptBASE64(key.getEncoded());
	}

	/**
	 * 取得公鑰
	 * 
	 * @param keyMap
	 * @return
	 * @throws Exception
	 */
	public static String getPublicKey(Map<String, Object> keyMap)
			throws Exception {
		Key key = (Key) keyMap.get(PUBLIC_KEY);

		return encryptBASE64(key.getEncoded());
	}

	/**
	 * 初始化金鑰
	 * 
	 * @return
	 * @throws Exception
	 */
	public static Map<String, Object> initKey() 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;
	}
}


簽名方法:

在開發後端服務的過程中,為了確保介面資料的準確性和不被修改,我們一般會對傳遞的引數進行一個簽名。

假如請求資料:appKey=test&a=xxxx&b=ssss&e=sss&d=sss&time=xxxxx&sign=sapodpasdpa

這個請求引數中,appKey為api請求方的key(請求方和服務端還儲存一份secret祕鑰),sign為資料的簽名,其餘為傳遞的引數。

sign的簽名演算法是對傳遞的引數進行鍵值升序排序,例如排序成這樣:

a=xxxx&appKey=test&b=ssss&d=sss&e=sss&time=xxxxx

請求方對這個引數進行簽名:sign = MD5(a=xxxx&appKey=test&b=ssss&d=sss&e=sss&time=xxxxx + 祕鑰)

然後服務端拿到請求的sign,同時也會拿到appKey,就可以找到對應的secret祕鑰,同樣對請求的引數進行升序排序後進行md5的簽名,再比較sign值是否相同,如果相同則表示資料未被修改。

同時為了介面的安全性,我們可以看到請求引數中有time欄位,我們還可以根據time時間來做請求的失效性處理,例如time和當前伺服器時間比較 大小返回在5分鐘之內還是有效,超出了說明這個請求的資料過期,可以拒絕請求。

PHP方法:

	/**
	 * 方法庫-sign簽名方法
	 * @param $array 需要加密的引數 
	 * @param $secret 祕鑰
	 * @param $signName sign的名稱,sign不會進行加密
	 */
	public function sign($array, $secret, $signName = "sign") {
		if (count($array) == 0) {
			return "";
		}
		ksort($array); //按照升序排序
		$str = "";
		foreach ($array as $key => $value) {
			if ($signName == $key) continue;
			$str .= $key . "=" . $value . "&";
		}
		$str = rtrim($str, "&");
		return md5($str . $secret);
	}


相關推薦

對稱加密/對稱加密/簽名演算法

對稱加密: 對稱加密是指,加密方和解密方使用同樣的祕鑰來進行加密和解密。 常用對稱加密: 1. DES演算法 DES演算法的入口引數有三個:Key、Data、Mode。其中Key為8個位元組共64位,是DES演算法的工作金鑰;Data也為8個位元組64位,是要被加密或被

JAVA實現RSA加密,對稱加密演算法

RSA.java package org.icesnow.jeasywx.util.security; import java.security.Key; import java.security.KeyFactory; import java.security.KeyPair;

對稱加密 對稱加密 不可逆加密演算法

根據金鑰型別不同可以將現代密碼技術分為兩類:對稱加密演算法(私鑰密碼體系)和非對稱加密演算法(公鑰密碼體系)。 1 對稱加密演算法中,資料加密和解密採用的都是同一個金鑰,因而其安全性依賴於所持有金鑰的安全性。 對稱加密演算法的主要優點是加密和解密速度快,加密強度高,且演算法公開. 缺點是實現金鑰的祕密分發困

資料傳輸加密——對稱加密演算法RSA+對稱演算法AES(適用於java,android和Web)

本篇文章已授權微信公眾號 guolin_blog (郭霖)獨家釋出 資料傳輸加密   在開發應用過程中,客戶端與服務端經常需要進行資料傳輸,涉及到重要隱私資訊時,開發者自然會想到對其進行加密,即使傳輸過程中被“有心人”擷取,也不會將資訊洩露。對於加密

數字摘要,對稱加密,對稱加密,數字簽名,數字證書

數字摘要 數字摘要也稱訊息摘要,由一個單向hash函式對一段訊息進行計算產生,不同的明文生成的密文總是不同的,而同樣的明文的密文一定相同。 訊息摘要能夠驗證訊息的完整性:如果訊息在傳遞的途

軟考之數字簽名 對稱加密 對稱加密

/*如有不對 概不負責*/   首先 對稱加密:是指加密解密使用的金鑰都是一樣的,對稱加密也稱為 私鑰密碼體制。大概在實際生活中就是 你有一個訊息要發給一個人類,你用對稱加密後發給他,然後你們事先肯定得約定好這個金鑰是什麼,然後他就用這個金鑰解開。這個金鑰肯定不能公開,所以

[svc]對稱加密/對稱加密細枝末節-如何做到數據傳輸的authentication/data integrity/confidentiality(私密)

ecc 數據完整性 安全 post 數字簽名 .html 模式 數字證書 大量 對稱/非對稱/混合加密的冷知識 數據在互聯網上傳輸,要考慮安全性. 講到安全,要從三方面考慮: 1、authentication 每一個IP包的認證,確保合法源的數據 2、data integ

對稱對稱加密

針對加密方式劃分為 對稱加密和非對稱加密 對稱加密:使用唯一祕鑰對資料進行加解密,其主要特點為速度快、使用方便、適合對大資料量進行加解密操作;主要缺點也比較明顯,需要事先約定祕鑰,當雙方通訊時就涉及到該祕鑰的交換,存在被截獲風險。 Aes演算法:將資料劃分為區塊,每個區塊

什麼是非對稱加密?對稱加密概念

什麼是非對稱加密 對稱加密演算法在加密和解密時使用的是同一個祕鑰;而非對稱加密演算法需要兩個金鑰來進行加密和解密,這兩個祕鑰是公開金鑰(public key,簡稱公鑰)和私有金鑰(private key,簡稱私鑰)   與對稱加密演算法不同,非對稱加密演算法需要兩個金鑰:

Git基本命令-遠端 以及 對稱對稱加密區別

git 基本命令 引擎 程式碼在本地提交,可以實現版本回退和前進。但是如果本地磁碟損壞,程式碼丟失,所以 我們要把程式碼往另一臺電腦(遠端伺服器)存一份。好像網盤。實現程式碼在不同客戶端 (電腦、筆記本、手機)拷貝下載程式碼,提交程式碼到遠端伺服器。 ssh 非對稱加密 ss

Java對稱對稱加密解密,AES與RSA

加密技術可以分為對稱與非對稱兩種. 對稱加密,解密,即加密與解密用的是同一把祕鑰,常用的對稱加密技術有DES,AES等 而非對稱技術,加密與解密用的是不同的祕鑰,常用的非對稱加密技術有RSA等 為什麼要有非對稱加密,解密技術呢 假設這樣一種場景A要傳送一段訊息給B,但是又

[svc]openssl對稱加密,對稱加密最佳實戰

 OpenSSL進行aes加密解密-對稱加密 建立檔案test.txt, 特意寫入中英文 # cd /tmp # echo "test測試" > test.txt 開始加密, 使用aes-128-cbc演算法, 也可以使用其他演算法

理論:HTTPS,TLS,SSL,TCP,UDP,對稱加密,對稱加密

HTTP:傳輸web內容的協議,軟水管(公開透明) TLS/SSL:不鏽鋼管 HTTPS:HTTP套上SSL,軟水管套上不鏽鋼管 TCP:傳輸層協議,HTTP基於TCP,面向連線 UDP:傳輸層協議,先傳不一定先到,面向非連線 對稱加密:加密和解密使用

Http協議與請求, Post請求與Get請求的區別,Base64和URL編碼,md5,sha-1加密,對稱對稱加密,支付寶微信第三方支付

Http協議與請求 Post請求 Post請求與Get請求的區別 Get請求的引數是直接放在url後面的,而Post請求是放在請求體中的 Get請求引數的長度會根據瀏覽器的不同實現有一定限制,而Post請求引數長度沒有限制

Java進階 八 Java加密技術之對稱加密 對稱加密 不可逆加密算法

歐洲 再次 div 數據安全 識別 交易 standard 計算 領域 對稱加密 非對稱加密 不可逆加密算法 根據密鑰類型不同可以將現代密碼技術分為兩類:對稱加密算法(私鑰密碼體系)和非對稱加密算法(公鑰密碼體系)。 1 對稱加密算法 原理 對稱加密算法中,數據

SpringCloud-分散式配置中心【加密-對稱加密

案例程式碼:https://github.com/q279583842q/springcloud-e-book 非對稱加密 一、什麼是非對稱加密(Asymmetric encryption) 二、Java-keytool 使用說明   非對稱加密我們需要生成對應的公鑰和私鑰,jdk中提供的有java-

密碼學(對稱對稱密碼 雜湊演算法)

目錄 密碼學 密碼學發展 對稱加密體制 非對稱加密體制 混合加密 雜湊演算法 數字簽名過程 密碼學的應用--網站認證 密碼學 密碼學發展 古典密碼:古代----19世紀末 近代密碼:20世紀初---1949年 現代密碼:1949(夏農

加解密,對稱對稱 簽名 數字證書原理

文中首先解釋了加密解密的一些基礎知識和概念,然後通過一個加密通訊過程的例子說明了加密演算法的作用,以及數字證書的出現所起的作用。接著對數字證書做一個詳細的解釋,並討論一下windows中數字證書的管理,最後演示使用makecert生成數字證書。如果發現文中有錯誤的地方,或

對稱對稱加解密

32位 tro 進行 ont 什麽 金融 被鎖 方式 str 對稱 DES: DES算法 再大多運用在 如信用卡持卡人的PIN的加密傳輸,IC卡與POS間的雙向認證、金融交易數據包的MAC校驗等領域 DES算法的入口參數有三

密碼學(對稱對稱密碼)

目錄 密碼學 密碼學發展 雜湊演算法 密碼學 密碼學發展 古典密碼:古代----19世紀末 近代密碼:20世紀初---1949年 現代密碼:1949(夏農發表的《保密系統的加密原理》)---1975 公鑰密碼:1976(W.Diffie和M.Hell