淺談常見的七種加密算法及實(shí)現(xiàn)

前言

數(shù)字簽名,信息加密是前后端開發(fā)都常用到的技術(shù),應(yīng)用場(chǎng)景包括了用戶登入唉擂、交易、信息通訊场靴、oath等等,不同的應(yīng)用場(chǎng)景也會(huì)需要用到不同的簽名加密算法≈及或者需要搭配不一樣的簽名加密算法咧欣,來(lái)達(dá)到業(yè)務(wù)目標(biāo)。這里簡(jiǎn)要介紹下集中常見的簽名加密算法及一些典型的應(yīng)用場(chǎng)景轨帜。

1魄咕、數(shù)字簽名


數(shù)字簽名,簡(jiǎn)單來(lái)說(shuō)就是通過提供可鑒別的數(shù)字信息驗(yàn)證自身身份的一種方式蚌父,一套數(shù)字簽名通常定義兩種互補(bǔ)的運(yùn)算哮兰,一個(gè)用于簽名,一個(gè)用于驗(yàn)證苟弛。分別由發(fā)送者持有能夠代表自己身份的私鑰(私鑰不可泄露)由接收者持有與私鑰對(duì)應(yīng)的公鑰喝滞,能夠在接收到發(fā)送者信息時(shí)驗(yàn)證其身份。

1.png

注意膏秫,圖中加密過程有別于公鑰加密右遭,。簽名最根本的用途是能夠唯一證明發(fā)送方的身份缤削,防止中間人攻擊窘哈,CSRF跨域身份偽造,基于這一點(diǎn)在諸如設(shè)備認(rèn)證亭敢、用戶認(rèn)證滚婉、第三方認(rèn)證等認(rèn)證體系中都會(huì)用到簽名算法。彼此的實(shí)現(xiàn)方式會(huì)有差異帅刀。

2满哪、加密和解密


數(shù)據(jù)加密的基本過程,就是對(duì)原來(lái)就是對(duì)原來(lái)為明文的文件或者數(shù)據(jù)進(jìn)行處理劝篷,使其成為不可讀的一段代碼,通常成為 密文民宿,來(lái)達(dá)到保護(hù)數(shù)據(jù)娇妓,而不被人非法獲取、閱讀的目的活鹰。

加密的你過程稱為解密哈恰,即將該編碼信息轉(zhuǎn)化為其原來(lái)數(shù)據(jù)的過程。

3志群、對(duì)稱加密和非對(duì)稱加密


加密算法分對(duì)稱加密和非對(duì)稱加密着绷,其中對(duì)稱加密算法的加密和解密密鑰相同,非對(duì)稱加密的加密密鑰和解密密鑰不同锌云,才外還有一類不需要密鑰的散列算法荠医。

常見的對(duì)稱加密算法 DES、3DES、AES等彬向,常見的非對(duì)稱算法主要有 RSA兼贡、DSA等,散列算法有SHA-1娃胆、MD5 等遍希。

對(duì)稱加密算法是應(yīng)用較早的加密算法,又稱為共享密鑰加密算法里烦,在對(duì)稱加密算法發(fā)中凿蒜,使用的密鑰只有一個(gè),發(fā)送和接收雙方都使用這個(gè)密鑰對(duì)數(shù)據(jù)進(jìn)行加密和解密胁黑。這就要求加密方和解密方都指定密鑰废封。

1.png

1、數(shù)據(jù)加密過程:在對(duì)稱加密算法中别厘,數(shù)據(jù)發(fā)送方將明文(原始數(shù)據(jù))和加密密鑰一起經(jīng)過特殊加密處理虱饿,生成復(fù)雜的加密密文進(jìn)行發(fā)送。

2触趴、數(shù)據(jù)解密過程:數(shù)據(jù)接收方收到密文后氮发,若想讀取原數(shù)據(jù),則需要使用加密使用的密鑰及相同算法的逆算法對(duì)加密的密文進(jìn)行解密冗懦,才能使其恢復(fù)成可讀明文爽冕。

非對(duì)稱加密算法又稱為公開密鑰加密算法,他需要兩個(gè)密鑰披蕉,一個(gè)分為公開密鑰(public key ),即公鑰颈畸,另一個(gè)為私有密鑰(private key)即私鑰。

因?yàn)榧用芎徒饷苁褂玫氖莾蓚€(gè)不同的密鑰没讲,所以這種算法稱為非對(duì)稱加密算法眯娱。

1.png

1、如果使用公鑰對(duì)數(shù)據(jù)進(jìn)行加密爬凑,只有用對(duì)應(yīng)的私鑰才能解密

2徙缴、如果使用私鑰對(duì)數(shù)據(jù)進(jìn)行加密,只有用對(duì)應(yīng)的公鑰才能解密

例子:甲方生成一對(duì)密鑰嘁信,并將其中的一把作為公鑰向其他人公開于样,得到該公鑰的乙方,使用該密鑰對(duì)機(jī)密信息進(jìn)行加密后再發(fā)送給甲方潘靖,甲方再使用自己保存的另一把專用密鑰(私鑰)穿剖,對(duì)加密后的信息進(jìn)行解密。

4卦溢、常見的簽名加密算法


4.1. MD5算法

MD5 用的是哈希函數(shù)糊余,它的典型應(yīng)用是對(duì)一段信息產(chǎn)生信息摘要秀又,以防止被纂改,嚴(yán)格來(lái)說(shuō)MD5 不是一種加密算法啄刹,而是摘要算法涮坐,無(wú)論是多長(zhǎng)的輸入,MD5 都會(huì)輸出長(zhǎng)度為128bits 的一個(gè)串誓军, (通常用 16 進(jìn)制 表示為 32 個(gè)字符)袱讹。 java 語(yǔ)言的代碼如下:

public class MD5Main {

    public static void main(String[] args) {
        String content = "this is a message";
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.digest(content.getBytes());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
}

4.2. SHA1算法

SHA1 是和 MD5 一樣流行的 消息摘要算法,然而 SHA1MD5安全性更強(qiáng)昵时。對(duì)于長(zhǎng)度小于 2 ^ 64 位的消息捷雕,SHA1 會(huì)產(chǎn)生一個(gè) 160 位的 消息摘要∫忌基于 MD5救巷、SHA1 的信息摘要特性以及 不可逆 (一般而言),可以被應(yīng)用在檢查 文件完整性 以及 數(shù)字簽名 等場(chǎng)景句柠。

public class MD5Main {

   public static void main(String[] args) {
       String content = "this is a message";
       try {
           MessageDigest md5 = MessageDigest.getInstance("SHA1");
           System.out.println("---------" + md5.digest(content.getBytes()));
       } catch (NoSuchAlgorithmException e) {
           e.printStackTrace();
       }
   }
}

4.3. HMAC算法

HMAC 是密鑰相關(guān)的浦译,哈希運(yùn)算消息認(rèn)證碼(Hash-based Message Authentication Code ),HMAC 運(yùn)算利用 哈希算法 (MD5溯职、SHA1 等)精盅, 以一個(gè)密鑰和一個(gè)消息為輸入,生成一個(gè)消息摘要為輸出谜酒。

HMAC 發(fā)送方接收方 都有的 key 進(jìn)行計(jì)算叹俏, 而沒有這把key 的第三方,則是無(wú)法計(jì)算出正確的散列值的僻族,這樣的話就可以防止數(shù)據(jù)被纂改粘驰。

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

測(cè)試結(jié)論:HMAC 算法實(shí)例在多線程環(huán)境下是不安全的,但是需要在多線程訪問時(shí)述么,進(jìn)行同步的輔助類蝌数,使用ThreadLocal 為每個(gè)線程緩存一個(gè)實(shí)例可以避免進(jìn)行鎖操作。

4.4. AES/DES/3DES算法

AES度秘、DES籽前、3DES 都是 對(duì)稱塊加密算法加解密 的過程是 可逆的敷钾。常用的有 AES128AES192肄梨、AES256 (默認(rèn)安裝的 JDK 尚不支持 AES256阻荒,需要安裝對(duì)應(yīng)的 jce 補(bǔ)丁進(jìn)行升級(jí) jce1.7jce1.8)众羡。

4.4.1. DES算法

DES 加密算法是一種分組密碼侨赡,以 64 位為 分組對(duì)數(shù)據(jù) 加密, 它的密鑰長(zhǎng)度時(shí)56 位,加密解密用同一算法羊壹。

DES 算法是對(duì)密鑰進(jìn)行保密蓖宦,而公開算法,包括加密和解密算法油猫,這樣只有掌握了和發(fā)送方相同密鑰的人才能解讀由DES 加密算法加密的密文數(shù)據(jù)稠茂。因此破解DES 加密算法實(shí)際上就是搜索密鑰的編碼。對(duì)于 56 位長(zhǎng)度的 密鑰 來(lái)說(shuō)情妖,如果用 窮舉法 來(lái)進(jìn)行搜索的話睬关,其運(yùn)算次數(shù)為 2 ^ 56 次。

4.4.2. 3DES算法

是基于 DES對(duì)稱算法毡证,對(duì) 一塊數(shù)據(jù)三個(gè)不同的密鑰 進(jìn)行 三次加密电爹,強(qiáng)度更高

4.4.3. AES算法

AES 加密算法是密碼學(xué)中的高級(jí)加密標(biāo)準(zhǔn)料睛,該加密算法采用對(duì)稱分組密碼體制丐箩,密鑰長(zhǎng)度最少支持為128 位、 192 位恤煞、256 位屎勘,分組長(zhǎng)度 128 位, 算法應(yīng)易于各種軟件和硬件實(shí)現(xiàn)阱州。這種加密算法是美國(guó)聯(lián)邦政府采用的 區(qū)塊加密標(biāo)準(zhǔn)挑秉。

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("錯(cuò)誤的初始密鑰");
        }
        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("錯(cuò)誤的初始密鑰");
        }
        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 加密算法是目前最有影響力的 公鑰加密算法,并且被普遍認(rèn)為是目前 最優(yōu)秀的公鑰方案 之一夜惭。RSA 是第一個(gè)能同時(shí)用于 加密數(shù)字簽名 的算法姻灶,它能夠 抵抗 到目前為止已知的 所有密碼攻擊,已被 ISO 推薦為公鑰數(shù)據(jù)加密標(biāo)準(zhǔn)诈茧。

RSA 加密算法基于一個(gè)十分簡(jiǎn)單的數(shù)論事實(shí):將兩個(gè)大素?cái)?shù)相乘十分容易产喉,但想要對(duì)其乘積進(jìn)行因式分解缺極其困難,因此可以將乘積公開作為加密密鑰敢会。

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作為加密算法實(shí)現(xiàn)
    }

    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 也是一種 非對(duì)稱加密算法曾沈,主要優(yōu)勢(shì)是在某些情況下,它比其他的方法使用 更小的密鑰鸥昏,比如 RSA 加密算法塞俱,提供 相當(dāng)?shù)幕蚋叩燃?jí) 的安全級(jí)別。不過一個(gè)缺點(diǎn)是 加密和解密操作 的實(shí)現(xiàn)比其他機(jī)制 時(shí)間長(zhǎng) (相比 RSA 算法吏垮,該算法對(duì) CPU 消耗嚴(yán)重)障涯。

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

5. 各種加密算法對(duì)比

5.1. 散列算法比較
名稱 安全性 速度
SHA-1
MD5
5.2. 對(duì)稱加密算法比較
名稱 密鑰名稱 運(yùn)行速度 安全性 資源消耗
DES 56位 較快
3DES 112位或168位
AES 128罐旗、192、256位
5.3. 非對(duì)稱加密算法比較
名稱 成熟度 安全性 運(yùn)算速度 資源消耗
RSA
ECC

5.4. 對(duì)稱算法與非對(duì)稱加密算法

5.4.1. 對(duì)稱算法
  1. 密鑰管理:比較難唯蝶,不適合互聯(lián)網(wǎng)九秀,一般用于內(nèi)部系統(tǒng)
  2. 安全性:中
  3. 加密速度:快好 幾個(gè)數(shù)量級(jí) (軟件加解密速度至少快 100 倍,每秒可以加解密數(shù) M 比特 數(shù)據(jù))粘我,適合大數(shù)據(jù)量的加解密處理
5.4.2. 非對(duì)稱算法
  1. 密鑰管理:密鑰容易管理
  2. 安全性:高
  3. 加密速度:比較慢鼓蜒,適合 小數(shù)據(jù)量 加解密或數(shù)據(jù)簽名

小結(jié)


本文介紹了 數(shù)字簽名加密和解密涂滴,對(duì)稱加密和非對(duì)稱加密友酱,然后詳細(xì)介紹了 MD5SHA-1柔纵,HMAC缔杉,DES/AESRSAECC 這幾種加密算法和代碼示例搁料。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末或详,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子郭计,更是在濱河造成了極大的恐慌霸琴,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,332評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件昭伸,死亡現(xiàn)場(chǎng)離奇詭異梧乘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)庐杨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,508評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門选调,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人灵份,你說(shuō)我怎么就攤上這事仁堪。” “怎么了填渠?”我有些...
    開封第一講書人閱讀 157,812評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵弦聂,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我氛什,道長(zhǎng)莺葫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,607評(píng)論 1 284
  • 正文 為了忘掉前任枪眉,我火速辦了婚禮捺檬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瑰谜。我一直安慰自己欺冀,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,728評(píng)論 6 386
  • 文/花漫 我一把揭開白布萨脑。 她就那樣靜靜地躺著隐轩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪渤早。 梳的紋絲不亂的頭發(fā)上职车,一...
    開封第一講書人閱讀 49,919評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音鹊杖,去河邊找鬼悴灵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛骂蓖,可吹牛的內(nèi)容都是我干的积瞒。 我是一名探鬼主播,決...
    沈念sama閱讀 39,071評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼登下,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼茫孔!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起被芳,我...
    開封第一講書人閱讀 37,802評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤缰贝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后畔濒,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剩晴,經(jīng)...
    沈念sama閱讀 44,256評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,576評(píng)論 2 327
  • 正文 我和宋清朗相戀三年侵状,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赞弥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,712評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡壹将,死狀恐怖嗤攻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情诽俯,我是刑警寧澤妇菱,帶...
    沈念sama閱讀 34,389評(píng)論 4 332
  • 正文 年R本政府宣布,位于F島的核電站暴区,受9級(jí)特大地震影響闯团,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜仙粱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,032評(píng)論 3 316
  • 文/蒙蒙 一房交、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧伐割,春花似錦候味、人聲如沸刃唤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)尚胞。三九已至,卻和暖如春帜慢,著一層夾襖步出監(jiān)牢的瞬間笼裳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,026評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工粱玲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留躬柬,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,473評(píng)論 2 360
  • 正文 我出身青樓抽减,卻偏偏與公主長(zhǎng)得像允青,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胯甩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,606評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 1. 介紹 數(shù)字簽名昧廷、信息加密 是前后端開發(fā)都經(jīng)常需要使用到的技術(shù),應(yīng)用場(chǎng)景包括了用戶登入偎箫、交易木柬、信息通訊、oau...
    luckyYU閱讀 10,586評(píng)論 1 6
  • 這篇文章主要講述在Mobile BI(移動(dòng)商務(wù)智能)開發(fā)過程中淹办,在網(wǎng)絡(luò)通信眉枕、數(shù)據(jù)存儲(chǔ)、登錄驗(yàn)證這幾個(gè)方面涉及的加密...
    雨_樹閱讀 2,366評(píng)論 0 6
  • 隨筆一 我一時(shí)不知道要怎么開這個(gè)頭怜森,其實(shí)這種情緒在上學(xué)的時(shí)候經(jīng)常出現(xiàn)速挑,因?yàn)槟莻€(gè)時(shí)候每天都有大把...
    浮生難閑閱讀 167評(píng)論 0 0
  • Mary一生最愛小f, 小f一生只愛Mary.
    巴爾斯緹閱讀 115評(píng)論 0 0
  • 馬云揭秘 : 2018政策大變動(dòng) , 窮人徹底翻身的機(jī)會(huì)終于來(lái)了 副硅。 馬云:1964年9月10日出生于浙江省杭州市...
    倪玉秋閱讀 118評(píng)論 0 0