淺談常見的七種驗籤以及加密算法實現

前言
數字簽名、信息加密 是前後端開發都經常需要使用到的技術,應用場景包括了用戶登入、交易、信息通訊、oauth 等等,不同的應用場景也會需要使用到不同的簽名加密算法,或者需要搭配不一樣的 簽名加密算法 來達到業務目標。這裏簡單的給大家介紹幾種常見的簽名加密算法和一些典型場景下的應用。

正文

  1. 數字簽名
    數字簽名,簡單來說就是通過提供 可鑑別 的 數字信息 驗證 自身身份 的一種方式。一套 數字簽名 通常定義兩種 互補 的運算,一個用於 簽名,另一個用於 驗證。分別由 發送者 持有能夠 代表自己身份 的 私鑰 (私鑰不可泄露),由 接受者 持有與私鑰對應的 公鑰 ,能夠在 接受 到來自發送者信息時用於 驗證 其身份。

注意:圖中 加密過程 有別於 公鑰加密,更多 介紹戳這裏。簽名 最根本的用途是要能夠唯一 證明發送方的身份,防止 中間人攻擊、CSRF 跨域身份僞造。基於這一點在諸如 設備認證、用戶認證、第三方認證 等認證體系中都會使用到 簽名算法 (彼此的實現方式可能會有差異)。

  1. 加密和解密
    2.1. 加密
    數據加密 的基本過程,就是對原來爲 明文 的文件或數據按 某種算法 進行處理,使其成爲 不可讀 的一段代碼,通常稱爲 “密文”。通過這樣的途徑,來達到 保護數據 不被 非法人竊取、閱讀的目的。

2.2. 解密
加密 的 逆過程 爲 解密,即將該 編碼信息 轉化爲其 原來數據 的過程。

  1. 對稱加密和非對稱加密
    加密算法分 對稱加密 和 非對稱加密,其中對稱加密算法的加密與解密 密鑰相同,非對稱加密算法的加密密鑰與解密 密鑰不同,此外,還有一類 不需要密鑰 的 散列算法。

常見的 對稱加密 算法主要有 DES、3DES、AES 等,常見的 非對稱算法 主要有 RSA、DSA 等,散列算法 主要有 SHA-1、MD5 等。

3.1. 對稱加密
對稱加密算法 是應用較早的加密算法,又稱爲 共享密鑰加密算法。在 對稱加密算法 中,使用的密鑰只有一個,發送 和 接收 雙方都使用這個密鑰對數據進行 加密 和 解密。這就要求加密和解密方事先都必須知道加密的密鑰。

數據加密過程:在對稱加密算法中,數據發送方 將 明文 (原始數據) 和 加密密鑰 一起經過特殊 加密處理,生成複雜的 加密密文 進行發送。

數據解密過程:數據接收方 收到密文後,若想讀取原數據,則需要使用 加密使用的密鑰 及相同算法的 逆算法 對加密的密文進行解密,才能使其恢復成 可讀明文。

3.2. 非對稱加密
非對稱加密算法,又稱爲 公開密鑰加密算法。它需要兩個密鑰,一個稱爲 公開密鑰 (public key),即 公鑰,另一個稱爲 私有密鑰 (private key),即 私鑰。

因爲 加密 和 解密 使用的是兩個不同的密鑰,所以這種算法稱爲 非對稱加密算法。

如果使用 公鑰 對數據 進行加密,只有用對應的 私鑰 才能 進行解密。

如果使用 私鑰 對數據 進行加密,只有用對應的 公鑰 才能 進行解密。

例子:甲方生成 一對密鑰 並將其中的一把作爲 公鑰 向其它人公開,得到該公鑰的 乙方 使用該密鑰對機密信息 進行加密 後再發送給甲方,甲方再使用自己保存的另一把 專用密鑰 (私鑰),對 加密 後的信息 進行解密。

  1. 常見的簽名加密算法
    4.1. MD5算法
    MD5 用的是 哈希函數,它的典型應用是對一段信息產生 信息摘要,以 防止被篡改。嚴格來說,MD5 不是一種 加密算法 而是 摘要算法。無論是多長的輸入,MD5 都會輸出長度爲 128bits 的一個串 (通常用 16 進制 表示爲 32 個字符)。

public static final byte[] computeMD5(byte[] content) {
try {
MessageDigest md5 = MessageDigest.getInstance(“MD5”);
return md5.digest(content);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}

4.2. SHA1算法
SHA1 是和 MD5 一樣流行的 消息摘要算法,然而 SHA1 比 MD5 的 安全性更強。對於長度小於 2 ^ 64 位的消息,SHA1 會產生一個 160 位的 消息摘要。基於 MD5、SHA1 的信息摘要特性以及 不可逆 (一般而言),可以被應用在檢查 文件完整性 以及 數字簽名 等場景。

public static byte[] computeSHA1(byte[] content) {
try {
MessageDigest sha1 = MessageDigest.getInstance(“SHA1”);
return sha1.digest(content);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}

4.3. HMAC算法
HMAC 是密鑰相關的 哈希運算消息認證碼(Hash-based Message Authentication Code),HMAC 運算利用 哈希算法 (MD5、SHA1 等),以 一個密鑰 和 一個消息 爲輸入,生成一個 消息摘要 作爲 輸出。

HMAC 發送方 和 接收方 都有的 key 進行計算,而沒有這把 key 的第三方,則是 無法計算 出正確的 散列值的,這樣就可以 防止數據被篡改。

package net.pocrd.util;
import net.pocrd.annotation.NotThreadSafe;
import net.pocrd.define.ConstField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;

@NotThreadSafe
public class HMacHelper {
private static final Logger logger = LoggerFactory.getLogger(HMacHelper.class);
private Mac mac;

/**
 * MAC算法可選以下多種算法
 * HmacMD5/HmacSHA1/HmacSHA256/HmacSHA384/HmacSHA512
 */
private static final String KEY_MAC = "HmacMD5";
public HMacHelper(String key) {
    try {
        SecretKey secretKey = new SecretKeySpec(key.getBytes(ConstField.UTF8), KEY_MAC);
        mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
    } catch (Exception e) {
        logger.error("create hmac helper failed.", e);
    }
}
public byte[] sign(byte[] content) {
    return mac.doFinal(content);
}

public boolean verify(byte[] signature, byte[] content) {
    try {
        byte[] result = mac.doFinal(content);
        return Arrays.equals(signature, result);
    } catch (Exception e) {
        logger.error("verify sig failed.", e);
    }
    return false;
}

}

測試結論:HMAC 算法實例在 多線程環境 下是 不安全的。但是需要在 多線程訪問 時,進行同步的輔助類,使用 ThreadLocal 爲 每個線程緩存 一個實例可以避免進行鎖操作。

4.4. AES/DES/3DES算法
AES、DES、3DES 都是 對稱 的 塊加密算法,加解密 的過程是 可逆的。常用的有 AES128、AES192、AES256 (默認安裝的 JDK 尚不支持 AES256,需要安裝對應的 jce 補丁進行升級 jce1.7,jce1.8)。

4.4.1. DES算法
DES 加密算法是一種 分組密碼,以 64 位爲 分組對數據 加密,它的 密鑰長度 是 56 位,加密解密 用 同一算法。

DES 加密算法是對 密鑰 進行保密,而 公開算法,包括加密和解密算法。這樣,只有掌握了和發送方 相同密鑰 的人才能解讀由 DES加密算法加密的密文數據。因此,破譯 DES 加密算法實際上就是 搜索密鑰的編碼。對於 56 位長度的 密鑰 來說,如果用 窮舉法 來進行搜索的話,其運算次數爲 2 ^ 56 次。

4.4.2. 3DES算法
是基於 DES 的 對稱算法,對 一塊數據 用 三個不同的密鑰 進行 三次加密,強度更高。

4.4.3. AES算法
AES 加密算法是密碼學中的 高級加密標準,該加密算法採用 對稱分組密碼體制,密鑰長度的最少支持爲 128 位、 192 位、256 位,分組長度 128 位,算法應易於各種硬件和軟件實現。這種加密算法是美國聯邦政府採用的 區塊加密標準。

AES 本身就是爲了取代 DES 的,AES 具有更好的 安全性、效率 和 靈活性。

import net.pocrd.annotation.NotThreadSafe;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

@NotThreadSafe
public class AesHelper {
private SecretKeySpec keySpec;
private IvParameterSpec iv;

public AesHelper(byte[] aesKey, byte[] iv) {
    if (aesKey == null || aesKey.length < 16 || (iv != null && iv.length < 16)) {
        throw new RuntimeException("錯誤的初始密鑰");
    }
    if (iv == null) {
        iv = Md5Util.compute(aesKey);
    }
    keySpec = new SecretKeySpec(aesKey, "AES");
    this.iv = new IvParameterSpec(iv);
}

public AesHelper(byte[] aesKey) {
    if (aesKey == null || aesKey.length < 16) {
        throw new RuntimeException("錯誤的初始密鑰");
    }
    keySpec = new SecretKeySpec(aesKey, "AES");
    this.iv = new IvParameterSpec(Md5Util.compute(aesKey));
}

public byte[] encrypt(byte[] data) {
    byte[] result = null;
    Cipher cipher = null;
    try {
        cipher = Cipher.getInstance("AES/CFB/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
        result = cipher.doFinal(data);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return result;
}

public byte[] decrypt(byte[] secret) {
    byte[] result = null;
    Cipher cipher = null;
    try {
        cipher = Cipher.getInstance("AES/CFB/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
        result = cipher.doFinal(secret);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return result;
}

public static byte[] randomKey(int size) {
    byte[] result = null;
    try {
        KeyGenerator gen = KeyGenerator.getInstance("AES");
        gen.init(size, new SecureRandom());
        result = gen.generateKey().getEncoded();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return result;
}

}

4.5. RSA算法
RSA 加密算法是目前最有影響力的 公鑰加密算法,並且被普遍認爲是目前 最優秀的公鑰方案 之一。RSA 是第一個能同時用於 加密 和 數字簽名 的算法,它能夠 抵抗 到目前爲止已知的 所有密碼攻擊,已被 ISO 推薦爲公鑰數據加密標準。

RSA 加密算法 基於一個十分簡單的數論事實:將兩個大 素數 相乘十分容易,但想要對其乘積進行 因式分解 卻極其困難,因此可以將 乘積 公開作爲 加密密鑰。

import net.pocrd.annotation.NotThreadSafe;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.Security;
import java.security.Signature;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

@NotThreadSafe
public class RsaHelper {
private static final Logger logger = LoggerFactory.getLogger(RsaHelper.class);
private RSAPublicKey publicKey;
private RSAPrivateCrtKey privateKey;

static {
    Security.addProvider(new BouncyCastleProvider()); //使用bouncycastle作爲加密算法實現
}

public RsaHelper(String publicKey, String privateKey) {
    this(Base64Util.decode(publicKey), Base64Util.decode(privateKey));
}

public RsaHelper(byte[] publicKey, byte[] privateKey) {
    try {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        if (publicKey != null && publicKey.length > 0) {
            this.publicKey = (RSAPublicKey)keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));
        }
        if (privateKey != null && privateKey.length > 0) {
            this.privateKey = (RSAPrivateCrtKey)keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey));
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public RsaHelper(String publicKey) {
    this(Base64Util.decode(publicKey));
}

public RsaHelper(byte[] publicKey) {
    try {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        if (publicKey != null && publicKey.length > 0) {
            this.publicKey = (RSAPublicKey)keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public byte[] encrypt(byte[] content) {
    if (publicKey == null) {
        throw new RuntimeException("public key is null.");
    }

    if (content == null) {
        return null;
    }

    try {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        int size = publicKey.getModulus().bitLength() / 8 - 11;
        ByteArrayOutputStream baos = new ByteArrayOutputStream((content.length + size - 1) / size * (size + 11));
        int left = 0;
        for (int i = 0; i < content.length; ) {
            left = content.length - i;
            if (left > size) {
                cipher.update(content, i, size);
                i += size;
            } else {
                cipher.update(content, i, left);
                i += left;
            }
            baos.write(cipher.doFinal());
        }
        return baos.toByteArray();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public byte[] decrypt(byte[] secret) {
    if (privateKey == null) {
        throw new RuntimeException("private key is null.");
    }

    if (secret == null) {
        return null;
    }

    try {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        int size = privateKey.getModulus().bitLength() / 8;
        ByteArrayOutputStream baos = new ByteArrayOutputStream((secret.length + size - 12) / (size - 11) * size);
        int left = 0;
        for (int i = 0; i < secret.length; ) {
            left = secret.length - i;
            if (left > size) {
                cipher.update(secret, i, size);
                i += size;
            } else {
                cipher.update(secret, i, left);
                i += left;
            }
            baos.write(cipher.doFinal());
        }
        return baos.toByteArray();
    } catch (Exception e) {
        logger.error("rsa decrypt failed.", e);
    }
    return null;
}

public byte[] sign(byte[] content) {
    if (privateKey == null) {
        throw new RuntimeException("private key is null.");
    }
    if (content == null) {
        return null;
    }
    try {
        Signature signature = Signature.getInstance("SHA1WithRSA");
        signature.initSign(privateKey);
        signature.update(content);
        return signature.sign();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public boolean verify(byte[] sign, byte[] content) {
    if (publicKey == null) {
        throw new RuntimeException("public key is null.");
    }
    if (sign == null || content == null) {
        return false;
    }
    try {
        Signature signature = Signature.getInstance("SHA1WithRSA");
        signature.initVerify(publicKey);
        signature.update(content);
        return signature.verify(sign);
    } catch (Exception e) {
        logger.error("rsa verify failed.", e);
    }
    return false;
}

}

4.6. ECC算法
ECC 也是一種 非對稱加密算法,主要優勢是在某些情況下,它比其他的方法使用 更小的密鑰,比如 RSA 加密算法,提供 相當的或更高等級 的安全級別。不過一個缺點是 加密和解密操作 的實現比其他機制 時間長 (相比 RSA 算法,該算法對 CPU 消耗嚴重)。

import net.pocrd.annotation.NotThreadSafe;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.Security;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

@NotThreadSafe
public class EccHelper {
private static final Logger logger = LoggerFactory.getLogger(EccHelper.class);
private static final int SIZE = 4096;
private BCECPublicKey publicKey;
private BCECPrivateKey privateKey;

static {
    Security.addProvider(new BouncyCastleProvider());
}

public EccHelper(String publicKey, String privateKey) {
    this(Base64Util.decode(publicKey), Base64Util.decode(privateKey));
}

public EccHelper(byte[] publicKey, byte[] privateKey) {
    try {
        KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
        if (publicKey != null && publicKey.length > 0) {
            this.publicKey = (BCECPublicKey)keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));
        }
        if (privateKey != null && privateKey.length > 0) {
            this.privateKey = (BCECPrivateKey)keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKey));
        }
    } catch (ClassCastException e) {
        throw new RuntimeException("", e);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public EccHelper(String publicKey) {
    this(Base64Util.decode(publicKey));
}

public EccHelper(byte[] publicKey) {
    try {
        KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
        if (publicKey != null && publicKey.length > 0) {
            this.publicKey = (BCECPublicKey)keyFactory.generatePublic(new X509EncodedKeySpec(publicKey));
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public byte[] encrypt(byte[] content) {
    if (publicKey == null) {
        throw new RuntimeException("public key is null.");
    }
    try {
        Cipher cipher = Cipher.getInstance("ECIES", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        int size = SIZE;
        ByteArrayOutputStream baos = new ByteArrayOutputStream((content.length + size - 1) / size * (size + 45));
        int left = 0;
        for (int i = 0; i < content.length; ) {
            left = content.length - i;
            if (left > size) {
                cipher.update(content, i, size);
                i += size;
            } else {
                cipher.update(content, i, left);
                i += left;
            }
            baos.write(cipher.doFinal());
        }
        return baos.toByteArray();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public byte[] decrypt(byte[] secret) {
    if (privateKey == null) {
        throw new RuntimeException("private key is null.");
    }
    try {
        Cipher cipher = Cipher.getInstance("ECIES", "BC");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        int size = SIZE + 45;
        ByteArrayOutputStream baos = new ByteArrayOutputStream((secret.length + size + 44) / (size + 45) * size);
        int left = 0;
        for (int i = 0; i < secret.length; ) {
            left = secret.length - i;
            if (left > size) {
                cipher.update(secret, i, size);
                i += size;
            } else {
                cipher.update(secret, i, left);
                i += left;
            }
            baos.write(cipher.doFinal());
        }
        return baos.toByteArray();
    } catch (Exception e) {
        logger.error("ecc decrypt failed.", e);
    }
    return null;
}

public byte[] sign(byte[] content) {
    if (privateKey == null) {
        throw new RuntimeException("private key is null.");
    }
    try {
        Signature signature = Signature.getInstance("SHA1withECDSA", "BC");
        signature.initSign(privateKey);
        signature.update(content);
        return signature.sign();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public boolean verify(byte[] sign, byte[] content) {
    if (publicKey == null) {
        throw new RuntimeException("public key is null.");
    }
    try {
        Signature signature = Signature.getInstance("SHA1withECDSA", "BC");
        signature.initVerify(publicKey);
        signature.update(content);
        return signature.verify(sign);
    } catch (Exception e) {
        logger.error("ecc verify failed.", e);
    }
    return false;
}

}

  1. 各種加密算法對比
    5.1. 散列算法比較
    名稱 安全性 速度
    SHA-1 高 慢
    MD5 中 快
    5.2. 對稱加密算法比較
    名稱 密鑰名稱 運行速度 安全性 資源消耗
    DES 56位 較快 低 中
    3DES 112位或168位 慢 中 高
    AES 128、192、256位 快 高 低
    5.3. 非對稱加密算法比較
    名稱 成熟度 安全性 運算速度 資源消耗
    RSA 高 高 中 中
    ECC 高 高 慢 高
    5.4. 對稱算法與非對稱加密算法
    5.4.1. 對稱算法
    密鑰管理:比較難,不適合互聯網,一般用於內部系統

安全性:中

加密速度:快好 幾個數量級 (軟件加解密速度至少快 100 倍,每秒可以加解密數 M 比特 數據),適合大數據量的加解密處理

5.4.2. 非對稱算法
密鑰管理:密鑰容易管理

安全性:高

加密速度:比較慢,適合 小數據量 加解密或數據簽名

小結
本文介紹了 數字簽名,加密和解密,對稱加密和非對稱加密,然後詳細介紹了 MD5,SHA-1,HMAC,DES/AES,RSA 和 ECC 這幾種加密算法和代碼示例。
————————————————
版權聲明:本文爲CSDN博主「零壹技術棧」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/baidu_22254181/article/details/82594072

對稱加密:密鑰只有一個,解密、解密都是這個密碼,加解密速度快,典型的對稱加密有DES、AES、RC4等
非對稱加密:密鑰成對出現,分別爲公鑰和私鑰,從公鑰無法推知私鑰,反之,從私鑰也無法推知公鑰,加密和解密使用不同的密鑰,公鑰加密需要私鑰解密,反之,私鑰加密需要公鑰解密。非對稱加密速度較慢,典型的非對稱算法有:RSA,DSA,DSS.
Hash算法,這是一種不可逆的算法,它常用於驗證數據的完整性。
對稱加密:下面介紹AES:

AES是典型的對稱加密算法,假設發送方要獲取用戶信息,如果沒有任何加密算法,發送方發送的是一個明文信息"獲取用戶信息",

未加密的情況下:

如果消息在網絡傳輸中被人截獲,即使無法篡改,也可以偷窺消息的內容,從而暴露了通信雙方的私密。

加密的情況:

具體的工作的步驟如下:

發送方利用密鑰123456,加密明文爲"獲取用戶信息",加密結果爲aaCURzhJGiOYIujQYwbocw==。
發送方把加密後的你內筒aaCURzhJGiOYIujQYwbocw傳送給接收方。
接收方收到密文aaCURzhJGiOYIujQYwbocw
,利用密鑰123456還原爲明文“獲取用戶信息”。
對稱加密算法是可逆的,它的主要作用 是保證私密信息不被泄露。

AES 算法的基本概念:密鑰、填充、模式。

密鑰:AES 支持三種長度的密鑰:128位,192位,256位,位數越多,安全性越高
填充:
1.NoPadding:不做任何填充,但是要求明文必須是16字節的整數倍

          2.PKCS5PAdding(默認):如果明文少於128bit,在明文末尾不足相應數量的字節,最後一個字符值等於缺少的自己數,其他字符填充隨機數。

模式:ESB模式(默認)、CBC模式、CTR模式、CTR模式、CFB模式、OFB模式等
MD5算法:

MD5算法就是信息摘要的一種實現,它可以從任意長度的明文字符串生成128位的哈希值。

下面以支付寶轉賬爲例:

不用MD5加密:

被篡改的情況下:

這種場景下就需要信息摘要技術了。信息摘要要把明文內容按某種規則生成一端哈希值,即使 明文信息只改動了一點,生成的記過也完全不同。

信息摘要生成規則( secret+param+secret):可以任意添加,只要客戶端和服務端加密規則一樣就可以。

信息摘要的三個步驟:

1.收集相關業務參數,這裏是金額和目標賬戶。

2.按照拼接規則拼接起來

3.利用MD5加密,生成128位的二進制

客戶端使用MD5(secret+金額_10000+目標賬戶_12345678+secret)生成MD5

服務端收到後獲取到用戶發送的三處,也使用相同的拼接規則進行加密:然後比對客戶端傳過來的MD5和生成的MD5,如相同,則簽名對比成功,信息沒被篡改。

非對稱加密:SHA

SHA也是一種生成信息摘要的算法,SHA有很多版本,最大的版本分類是SHA-1和SHA-2,SHA-2又分了很多子版本;

常用:
概述
md5及RSA加密算法是我們比較常見的兩種加密算法,也是經常使用到的。我主要是利用md5的C Lib庫實現md5加密功能,使用openssl庫API實現RSA加密。這裏做個筆記,下次用到就可以直接使用了。

MD5
MD5消息摘要算法(英語:MD5 Message-Digest Algorithm),一種被廣泛使用的密碼散列函數,可以產生出一個128位(16字節)的散列值(hash value),用於確保信息傳輸完整一致。(摘自維基百科)

對於MD5加密,現在主要用於校驗的一個功能,比如文件傳輸中,服務器預先給文件計算md5值,在客戶下載時同時把md5值發送給客戶,客戶通過計算文件的md5值,比對兩個值是否相等來判斷文件下載是否成功。

這裏是我的代碼地址:https://github.com/dancersky/md5_demo.

RSA
RSA加密算法是一種非對稱加密算法。在公開密鑰加密和電子商業中RSA被廣泛使用。(摘自維基百科)

非對稱加密需要兩個密鑰,一個公鑰一個私鑰。一般都是私鑰是自己保管好不給任何人,公鑰可以發佈。對於明文,使用公鑰加密則需用私鑰解密,反之用私鑰加密則需用公鑰解密。

我這邊主要是利用openssl的C庫,實現了對明文的RSA加解密。主要環境在ubuntu14.04上。

這裏是我代碼地址以及公鑰私鑰生成的一些說明:https://github.com/dancersky/rsa_demo.
————————————————
版權聲明:本文爲CSDN博主「Dancer__Sky」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。

————————————————
版權聲明:本文爲CSDN博主「IT_搬運工」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/fd2025/article/details/80035647

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章