多語(yǔ)言3DES加解密舉例

工作中經(jīng)常涉及和不同編程語(yǔ)言使用3DES加解密的對(duì)接問(wèn)題米碰,很多語(yǔ)言對(duì)于同一種加密算法的細(xì)節(jié)處理還是有些出入的补憾,典型的如加密模式叛拷、填充方法。

3DES加解密簡(jiǎn)介

DES使用分塊加密浴鸿,加密密鑰為56位井氢,塊大小為64位。由于56位版本的DES加密非常容易破解(一般機(jī)器一天以內(nèi))赚楚,就有了和DES兼容性較好的3DES算法毙沾。

原理

3DES加密算法表示為C=EncryptK3(DecryptK2(EncryptK1(message),如果K1宠页、K2左胞、K3為密鑰,如果各不相同举户,則相當(dāng)于加密密鑰長(zhǎng)度為112(由于中途相遇攻擊)烤宙;解密算法表示為message=DecryptK1((EncryptK2(DecryptK3(C)))

以加密算法舉例:

  • 使用了3次DES算法,有3個(gè)密鑰
  • 加密時(shí)第一個(gè)密鑰K1用來(lái)加密消息(P)俭嘁,輸出C1密文
  • 第二個(gè)密鑰K2用來(lái)解密C1躺枕,輸出C2密文
  • 第三個(gè)密鑰K3用來(lái)加密C2,輸出C3密文

分組密碼工作模式

分組密碼的工作模式允許使用同一個(gè)分組密碼密鑰對(duì)多于一塊的數(shù)據(jù)進(jìn)行加密,并保證其安全性拐云。分組密碼自身只能加密長(zhǎng)度等于密碼分組長(zhǎng)度的單塊數(shù)據(jù)罢猪,若要加密變長(zhǎng)數(shù)據(jù),則數(shù)據(jù)必須先被劃分為一些單獨(dú)的密碼塊叉瘩。通常而言膳帕,最后一塊數(shù)據(jù)也需要使用合適填充方式將數(shù)據(jù)擴(kuò)展到匹配密碼塊大小的長(zhǎng)度。一種工作模式描述了加密每一數(shù)據(jù)塊的過(guò)程薇缅,并常常使用基于一個(gè)通常稱為初始化向量的附加輸入值以進(jìn)行隨機(jī)化危彩,以保證安全。

對(duì)于分組密碼工作模式的介紹可參考wiki

常見(jiàn)的工作模式包括ECB泳桦,CBC汤徽,OFB和CFB等。

分組密碼初始化向量(IV)

用于將加密隨機(jī)化的一個(gè)位塊灸撰,由此即使同樣的明文被多次加密也會(huì)產(chǎn)生不同的密文谒府,避免了較慢的重新產(chǎn)生密鑰的過(guò)程。

分組密碼填充

塊密碼只能對(duì)確定長(zhǎng)度的數(shù)據(jù)塊進(jìn)行處理梧奢,而消息的長(zhǎng)度通常是可變的狱掂。因此部分模式(即ECB和CBC)需要最后一塊在加密前進(jìn)行填充演痒。

加密后字節(jié)轉(zhuǎn)文本

對(duì)消息加密后通常會(huì)得到字節(jié)數(shù)組亲轨,在傳輸時(shí)一般會(huì)使用BASE64或HEX等進(jìn)行編碼。

多語(yǔ)言舉例

統(tǒng)一起見(jiàn)鸟顺,工作模式選擇ECB惦蚊,填充模式選擇PKCS5Padding或使用8-byte塊大小的PKCS7Padding(兩種填充模式差別可參考StackExchange),使用base64將加密后字節(jié)轉(zhuǎn)換為文本密文讯嫂。

大家在使用時(shí)蹦锋,一定記得要明確工作模式(mode of operation)和填充模式(padding),因?yàn)?em>不同語(yǔ)言(甚至同一種語(yǔ)言不同版本)中對(duì)于工作模式和填充模式的實(shí)現(xiàn)是可以自由選擇的欧芽。

Java

代碼

public static String encrypt(String text, String key){
    try {
      DESedeKeySpec spec = new DESedeKeySpec(key.getBytes());
      SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("desede");
      Key destKey = keyFactory.generateSecret(spec);
      Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");
      cipher.init(Cipher.ENCRYPT_MODE, destKey);
      byte[] textBs = text.getBytes("UTF-8");
      byte[] cipherText = cipher.doFinal(textBs);
      BASE64Encoder b64encoder = new BASE64Encoder();
      return b64encoder.encode(cipherText);
    } catch (InvalidKeyException e) {
      e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (InvalidKeySpecException e) {
      e.printStackTrace();
    } catch (NoSuchPaddingException e) {
      e.printStackTrace();
    } catch (BadPaddingException e) {
      e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
      e.printStackTrace();
    }

    return null;
  }
  public static String decrypt(String decryptedText, String key){

    try {

      BASE64Decoder b64decoder = new BASE64Decoder();
      byte[] textBs = b64decoder.decodeBuffer(decryptedText);
      DESedeKeySpec spec = new DESedeKeySpec(key.getBytes());
      SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("desede");
      Key destKey = keyFactory.generateSecret(spec);
      Cipher cipher = Cipher.getInstance("desede" + "/ECB/PKCS5Padding");
      cipher.init(Cipher.DECRYPT_MODE, destKey);
      byte[] cipherText = cipher.doFinal(textBs);
      return new String(cipherText,"UTF-8");
    } catch (InvalidKeyException e) {
      e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (InvalidKeySpecException e) {
      e.printStackTrace();
    } catch (NoSuchPaddingException e) {
      e.printStackTrace();
    } catch (BadPaddingException e) {
      e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    } catch (IllegalBlockSizeException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }

    return null;
  }

注意

注意在使用Cipher.getInstance選擇加密解密算法時(shí)莉掂,如果選擇desede,也即忽略工作模式和填充模式后千扔,將使用默認(rèn)的"/ECB/PKCS5Padding"憎妙。由于其他語(yǔ)言的默認(rèn)方式可能不同,將導(dǎo)致不同語(yǔ)言在加解密時(shí)異常曲楚。

使用到生產(chǎn)環(huán)境時(shí)厘唾,需要處理異常

Python

代碼

Python2

# encoding:utf-8

from Crypto.Cipher import DES3
import base64

# 加密模式 ECB , 填充模式 PKCS5Padding
BS = DES3.block_size
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[0:-ord(s[-1])]

'''
  DES3加密
  text 待加密字符串
  key 密鑰,使用appsecret
'''
def encrypt(text, key):
    text = pad(text)
    cipher = DES3.new(key,DES3.MODE_ECB)
    m = cipher.encrypt(text)
    m = base64.b64encode(m)
    return m.decode('utf-8')

'''
  DES3解密
  decrypted_text 解密字符串
  key 密鑰龙誊,使用appsecret
'''
def decrypt(decrypted_text, key):
    text = base64.b64decode(decrypted_text)
    cipher = DES3.new(key, DES3.MODE_ECB)
    s = cipher.decrypt(text)
    s = unpad(s)
    return s.decode('utf-8')


if __name__ == '__main__':
    print encrypt('Hello','1234567887654321')
    print decrypt('qO8nDeYzqTs=','1234567887654321')

Python3

# encoding:utf-8

from Crypto.Cipher import DES3
import base64

# 加密模式 ECB , 填充模式 PKCS5Padding
BS = DES3.block_size
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
unpad = lambda s : s[0:-s[-1]]

'''
  DES3加密
  參數(shù):
    text str 待加密字符串
    key str 密鑰抚垃,使用appsecret
  返回:
    str 加密后的字符串
'''
def encrypt(text, key):
    text = pad(text)
    cipher = DES3.new(key,DES3.MODE_ECB)
    m = cipher.encrypt(text) # m is bytes
    #m = base64.encodestring(m) # 會(huì)追加\n
    m = base64.b64encode(m)
    decrypted_text = m.decode('utf-8')
    return decrypted_text

'''
  DES3解密
  參數(shù):
    decrypted_text str 解密字符串
    key str 密鑰,使用appsecret
  返回:
    str 解密后的原始字符串
'''
def decrypt(decrypted_text, key):
    decrypted_bytes = bytes(decrypted_text, encoding='utf-8')
    #text = base64.decodestring(decrypted_bytes) #
    text = base64.b64decode(decrypted_bytes) #
    cipher = DES3.new(key, DES3.MODE_ECB)
    s = cipher.decrypt(text)
    s = unpad(s)
    s = s.decode('utf-8') # unpad and decode bytes to str
    return s


if __name__ == '__main__':
    print(encrypt('Hello','1234567887654321'))
    print(decrypt('qO8nDeYzqTs=','1234567887654321'))

注意

注意base64的encodestring已不推薦使用,且會(huì)在末尾加入"\n",使用b64encode代替鹤树。

python2中cipher.decryptcipher.encrypt以及base64.b64encodebase64.b64decode返回的是str铣焊,而python3中返回的是bytes。所以python3中unpad時(shí)無(wú)需再使用ord獲取字符的對(duì)應(yīng)ascii數(shù)值罕伯。

NodeJS

代碼

var crypto = require('crypto');
var key = '123456781234567812345678'; //加密的秘鑰 app secret
var demo_encryped = 'oVmfzWxhH88=';
var demo_decryped = 'Hello';

encrypt = function (str) {
    var cipher = crypto.createCipheriv('des-ede3', key, new Buffer(0));
    var crypted = cipher.update(str, 'utf8', 'base64');  // data[, input_encoding][, output_encoding]
    crypted += cipher.final('base64');
    return crypted;
}

decrypt = function(str) {
    var decipher = crypto.createDecipheriv('des-ede3', key, new Buffer(0));
    var dec = decipher.update(str, 'base64', 'utf8');
    dec += decipher.final('utf8');
    return dec;
}

console.log(encrypt(demo_decryped))
console.log(decrypt(demo_encryped))

注意

nodejs中的crypto依賴openssl粗截,使用>openssl list-cipher-algorithms獲取支持的算法列表。 如果需要選擇其他的算法捣炬,可參考o(jì)penssl熊昌。

desede其實(shí)是3des的別稱(反過(guò)來(lái)說(shuō)也可以)。

注意使用nodejs時(shí)湿酸,要使用createDecipheriv婿屹,IV可傳入new Buffer(0)

CSharp

代碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace ConsoleApplication4
{
    class Program
    {
        public static string Encrypt3DES(string a_strString, string a_strKey)
        {
            TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();

            DES.Key = ASCIIEncoding.ASCII.GetBytes(a_strKey);
            DES.Mode = CipherMode.ECB;

            ICryptoTransform DESEncrypt = DES.CreateEncryptor();

            byte[] Buffer = UTF8Encoding.UTF8.GetBytes(a_strString);
            return Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
        }
        public static string Decrypt3DES(string a_strString, string a_strKey)
        {
            TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();

            DES.Key = ASCIIEncoding.ASCII.GetBytes(a_strKey);
            DES.Mode = CipherMode.ECB;
            DES.Padding = System.Security.Cryptography.PaddingMode.PKCS7;

            ICryptoTransform DESDecrypt = DES.CreateDecryptor();

            string result = "";
            try
            {
                byte[] Buffer = Convert.FromBase64String(a_strString);
                byte[] temp = DESDecrypt.TransformFinalBlock(Buffer, 0, Buffer.Length);
                result = UTF8Encoding.UTF8.GetString(temp);
            }
            catch (Exception e)
            {
                Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
            }
            return result;
        }
        static void Main()
        {
            // Console.WriteLine("hello world");
            // Console.ReadLine();
            System.Text.Encoding utf8 = System.Text.Encoding.UTF8;
            string sourceTxt = "Hello";
            string appSecert = "123456781234567812345678";

            string result = Encrypt3DES(sourceTxt, appSecert);
            Console.WriteLine(result);
            Console.ReadLine();

            string result2 = Decrypt3DES(result, appSecert);
            Console.WriteLine(result2);
            Console.ReadLine();
        }
    }
}

PHP

代碼

<?php
 //定義3DES加密key
define('CRYPT_KEYS', '123456781234567812345678');


class DES {
    private $key = CRYPT_KEYS;
    //只有CBC模式下需要iv,其他模式下iv會(huì)被忽略 
    private $iv = '';

    /**
    * 加密
    */
    public  function encrypt($value) {
        //先確定加密模式推溃,此處以ECB為例
        $td = mcrypt_module_open ( MCRYPT_3DES,'', MCRYPT_MODE_ECB,'');
        //$iv = pack ( 'H16', $this->iv );
        $value = $this->PaddingPKCS7 ( $value ); //填充
        //$key = pack ( 'H48', $this->key );
        mcrypt_generic_init ( $td, $this->key, $this->iv);
        $ret = base64_encode ( mcrypt_generic ( $td, $value ) );
        mcrypt_generic_deinit ( $td );
        mcrypt_module_close ( $td );
        return $ret;
    }

    /**
    * 解密
    */
    public  function decrypt($value) {
        $td = mcrypt_module_open ( MCRYPT_3DES, '', MCRYPT_MODE_ECB, '' );
        //$iv = pack ( 'H16', $this->iv );
        //$key = pack ( 'H48', $this->key );
        mcrypt_generic_init ( $td, $this->key,$this->iv );
        $ret = trim ( mdecrypt_generic ( $td, base64_decode ( $value ) ) );
        $ret = $this->UnPaddingPKCS7 ( $ret );
        mcrypt_generic_deinit ( $td );
        mcrypt_module_close ( $td );
        return $ret;
    }

    private  function PaddingPKCS7($data) {
        $padlen =  8 - strlen( $data ) % 8 ;
        for($i = 0; $i < $padlen; $i ++)
            $data .= chr( $padlen );
        return $data;
    }

    private  function UnPaddingPKCS7($data) {
        $padlen = ord (substr($data, (strlen( $data )-1), 1 ) );
        if ($padlen > 8 )
            return false;

        for($i = -1*($padlen-strlen($data)); $i < strlen ( $data ); $i ++) {
            if (ord ( substr ( $data, $i, 1 ) ) != $padlen)return false;
        }

        return substr ( $data, 0, -1*($padlen-strlen ( $data ) ) );
    }

}

CPP

代碼

#include <string>
#include <openssl/des.h>
#include <openssl/evp.h>

#pragma comment(lib, "libcrypto.lib")
#pragma comment(lib, "libssl.lib")
class Des {
private:
    static const int CFBMODE = 64;

public:

    static std::string encrypt(std::string tmp_key, std::string in) {
        unsigned char key[24];

        memset(key, 0, sizeof(key));
        memcpy(key, tmp_key.c_str(), sizeof(key));

        DES_key_schedule schedule;
        DES_key_schedule schedule2;
        DES_key_schedule schedule3;
        DES_cblock desKey = { 0 };

        memcpy(desKey, key, 8);
        DES_set_key_unchecked(&desKey, &schedule);
        memcpy(desKey, key + 8, 8);
        DES_set_key_unchecked(&desKey, &schedule2);
        memcpy(desKey, key + 16, 8);
        DES_set_key_unchecked(&desKey, &schedule3);
        int i = 0;
        const size_t paddingLength = (8 - in.length() % 8);

        unsigned char padding[8];
        memset(padding, 8 - (in.length() % 8), 8);

        if (paddingLength)
        {
            in.append((char*)padding, paddingLength);
        }

        size_t dataLength = paddingLength + in.length();
        char tmp_buf[8];
        memset(tmp_buf, 0, 8);
        std::string data;
        //data.reserve(dataLength);
        unsigned char input[8];
        for (size_t i = 0; i < (dataLength / 8); i++)
        {
            /*
            DES_ede3_cfb_encrypt((const unsigned char*)in.c_str() + (i * 8), (unsigned char*)tmp_buf, CFBMODE, 8, &schedule,
                &schedule2, &schedule3, &iv,
                DES_ENCRYPT);
            */
            //memset(input, 0, 8);
            memcpy(input, in.c_str() + (i * 8), 8);

            DES_ecb3_encrypt((const_DES_cblock*)input, (DES_cblock*)tmp_buf,&schedule, &schedule2, &schedule3, DES_ENCRYPT);

            data.append(tmp_buf, sizeof(tmp_buf));
        }
        return data;
    }

    static std::string decrypt(std::string tmp_key, std::string in) {
        //偏移向量
        //24位加密key仇穗,3des下秘鑰必須為24位
        unsigned char key[24];

        memset(key, 0, sizeof(key));
        memcpy(key, tmp_key.c_str(), sizeof(key));

        DES_key_schedule schedule;
        DES_key_schedule schedule2;
        DES_key_schedule schedule3;
        DES_cblock desKey = { 0 };
        DES_cblock iv = { 0 };
        memcpy(desKey, key, 8);
        DES_set_key_unchecked(&desKey, &schedule);
        memcpy(desKey, key + 8, 8);
        DES_set_key_unchecked(&desKey, &schedule2);
        memcpy(desKey, key + 16, 8);
        DES_set_key_unchecked(&desKey, &schedule3);
        int i = 0;
        std::string padding;
        unsigned char input[8];
        unsigned char tmp_buf[8];
        //memset(tmp_buf, 0, 8);
        for (size_t i = 0; i < (in.length() / 8); i++)
        {
            /*
            DES_ede3_cfb_encrypt((const unsigned char*)in.c_str() + (i * 8), (unsigned char*)tmp_buf, CFBMODE, 8, &schedule,
                &schedule2, &schedule3, &iv,
                DES_DECRYPT);
            */
            memcpy(input, in.c_str() + (i * 8), 8);
            DES_ecb3_encrypt((const_DES_cblock*)input, (DES_cblock*)tmp_buf,  &schedule,
                &schedule2, &schedule3, DES_DECRYPT);

            if (i == ((in.length() / 8) - 1) && tmp_buf[7] >= 0x01 && tmp_buf[7] <= 0x08)
            {
                padding.append((char *)tmp_buf, 8 - tmp_buf[7]);
            }
            else
            {
                padding.append((char *)tmp_buf, 8);
            }
        }
        return padding;
    }

};

C++不懂,同事幫忙寫(xiě)的昵观。

以上代碼可以在我的Github上找到箫爷。


參考:
1 A Security Site
2 使用 PyCrypto 進(jìn)行 AES/ECB/PKCS#5(7) 加密
3 https://github.com/eXcellme/tripledes-demo
4 PKCS5Padding和PKCS7Padding的區(qū)別
5 StackOverflow Difference between DESede and TripleDES for cipher.getInstance()
6 Python2.7 base64 doc , Python3.6 base64 doc
7 GrepCode com.sun.crypto.provider.DESedeCipher OpenJDK8實(shí)現(xiàn)
8 YouTube - AES DES 3DES簡(jiǎn)介
9 YouTube - ECB vs CBC
10 Nodejs crypto api
11 中途相遇攻擊Wiki
12 分組密碼工作模式Wiki

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市硬萍,隨后出現(xiàn)的幾起案子扩所,更是在濱河造成了極大的恐慌,老刑警劉巖朴乖,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祖屏,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡买羞,警方通過(guò)查閱死者的電腦和手機(jī)袁勺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)畜普,“玉大人期丰,你說(shuō)我怎么就攤上這事〕蕴簦” “怎么了钝荡?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)儒鹿。 經(jīng)常有香客問(wèn)我化撕,道長(zhǎng),這世上最難降的妖魔是什么约炎? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任植阴,我火速辦了婚禮蟹瘾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掠手。我一直安慰自己憾朴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布喷鸽。 她就那樣靜靜地躺著众雷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪做祝。 梳的紋絲不亂的頭發(fā)上砾省,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天,我揣著相機(jī)與錄音混槐,去河邊找鬼编兄。 笑死,一個(gè)胖子當(dāng)著我的面吹牛声登,可吹牛的內(nèi)容都是我干的狠鸳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼悯嗓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼件舵!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起脯厨,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤铅祸,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后俄认,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體个少,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年眯杏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壳澳。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡岂贩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出巷波,到底是詐尸還是另有隱情萎津,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布抹镊,位于F島的核電站锉屈,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏垮耳。R本人自食惡果不足惜颈渊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一遂黍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧俊嗽,春花似錦雾家、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至竹揍,卻和暖如春敬飒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背芬位。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工驶拱, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人晶衷。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓蓝纲,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親晌纫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子税迷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

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

  • 本文主要介紹移動(dòng)端的加解密算法的分類、其優(yōu)缺點(diǎn)特性及應(yīng)用锹漱,幫助讀者由淺入深地了解和選擇加解密算法箭养。文中會(huì)包含算法的...
    蘋(píng)果粉閱讀 11,505評(píng)論 5 29
  • 0x01 目錄 常見(jiàn)編碼: ASCII編碼 Base64/32/16編碼 shellcode編碼 Quoted-p...
    H0f_9閱讀 12,783評(píng)論 2 17
  • 這篇文章主要講述在Mobile BI(移動(dòng)商務(wù)智能)開(kāi)發(fā)過(guò)程中,在網(wǎng)絡(luò)通信哥牍、數(shù)據(jù)存儲(chǔ)毕泌、登錄驗(yàn)證這幾個(gè)方面涉及的加密...
    雨_樹(shù)閱讀 2,432評(píng)論 0 6
  • 1 基礎(chǔ) 1.1 對(duì)稱算法 描述:對(duì)稱加密是指加密過(guò)程和解密過(guò)程使用相同的密碼。主要分:分組加密嗅辣、序列加密撼泛。 原理...
    御淺永夜閱讀 2,400評(píng)論 1 4
  • 關(guān)于拖延癥的文章很多,這確實(shí)讓很多人苦不堪言澡谭,本人就深受其害愿题,最近無(wú)意看到了一則把牛頓定律與拖延癥關(guān)聯(lián)到一起的文章...
    tballer閱讀 507評(píng)論 4 2