星期三, 12月 21, 2016

大有量長夾開箱(貓吉鞄製所)

聖誕節交換禮物時,

不小心讓公主大人遇見正在製作手工皮件的朋友,

說遲時,那時快,公主立馬開啟採購模式,

直接當場下單~(攤手~該來的始終跑不掉~XDD)

製作好後,朋友非常貼心,

拿了一個印了可愛貓吉的盒子裝著,


大家都那麼熟了!

下次可以省下來啊~XDD


這就讓我們來看看公主大人買了什麼吧!

一個長夾和一個小的名片/零錢包


長夾攤開整個容量非常大,


可以把整隻 iPhone 6 Plus 和護照放進去都沒有問題,


名片/零錢包的大小也剛剛好,


攤開後除了可以放名片外,還可以放上零錢,


如果出門一下下,不想帶著長夾,還可以塞個卡和幾張鈔票就可以出門了~

非常的樸素的設計,而且實用,
(看著公主大人心滿意足的表情,這次不用跪算盤了~XDD)

有興趣的朋友,也可以去貓吉鞄制所看看,也有提供客製服務喔~

星期四, 7月 21, 2016

ARTBOX 26 吋 PC 玫瑰金鏡面鋁框行李箱

奇怪~怎麼我房間又多了東西呢?!
(又來~每次打開箱文都要演一次,累不累啊~)

而且還蠻大一箱~


究竟是什麼東西呢?!


這莫非是上帝知道我準備出國旅遊了!所以送來的禮物?!


好吧~演不下去了~XDD

其實是很久沒有寫部落格了~

所以就補開一下去年去日本旅遊前,新買來給公主大人用的行李箱囉~

沒辦法!因為公主的行李箱實在是用太久了~
(其實是公主行李箱實在是太舊舊髒髒的,真心覺得...該換了...這算爆料嗎~XDD)

而且奴才小的實在捨不得公主大人這麼節儉~

所以呢~就擅自買了個公主大人喜歡的玫瑰金行李箱給公主大人囉!
(公主大人實在太明顯了~一直在看玫瑰金的大行李箱~時不時都跟我說好漂亮哦~嘖嘖嘖~)

讓我們來看看完整的行李箱吧~


說真的玫瑰金真的蠻好看的,而且26吋的大小,給公主用絕對不嫌小~
(事實證明,公主還是把它塞滿了~XDD)


行李箱裡面的空間個人是覺得非常大,


放入我的行李讓大家感受一下裡面實際的大小,

看來對我而言,五天四夜的日本行,這行李箱太大了些!


請不要不相信,這樣就是我全部的行李~是不是太大了~XDD


厲害的是~我們回國的時候他是滿的~XDD

這行李箱的多段式鋁合金拉把拉起來的樣子~


上側回彈把手還蠻好提拿行李箱的,

加上新買的吉卜力行李吊牌一起入鏡~XDD


TSA全球認證海關鎖不會很卡很難使用,

側邊的回彈把手也蠻好提拿的,


鋁框的密合對非常好,而且有一體成形的防撞護角,

當然是不希望撞到,但是每次提領行李的時候都會傷到,

幸好這個行李箱整個有包膜。


實際使用上非常滿意,

不過呢~過海關去拿行李的時候還是有傷到,

感恩外面那層保護的膠膜,

但是應該不堪再次受創,

所以回國後額外買了一個 Deseno 的透明防刮旅行箱套,

如果喜歡而且在意行李箱外觀的朋友,除了購買行李箱外,還是建議買個旅行箱套喔!
(因為爆公主大人的料,所以我現在要負荊請罪去了~QQ~~~~~)


星期五, 7月 08, 2016

TripleDES/AES(CBC/PKCS7) 在 .NET/Java/PHP/Delphi 加解密互通範例

加解密在不同程式語言中一直給程式設計師很多困擾,

尤其是 .NET 到其他程式語言,

所以寫這篇以 .NET 為基礎,

以 TripleDES/AES 加解密,Cipher Mode 使用 CBC,Padding Mode 使用 PKCS7,

提供 .NET/Java/PHP/Delphi 加解密程式範例:
(備註:因為我沒有 Delphi 環境,所以 Delphi 的範例是摘自朋友 kuraki5336 網誌)

.NET 範例 (TripleDES/DES/AES):
using System;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace Sample
{
    /// <summary>
    /// 對稱式加密模式。
    /// </summary>
    public enum SymmetricMode
    {
        /// <summary>
        /// AES 加密演算法。
        /// </summary>
        AES,
        /// <summary>
        /// DES 加密演算法。
        /// </summary>
        DES,
        /// <summary>
        /// TripleDES 加密演算法。
        /// </summary>
        TripleDES
    }
    /// <summary>
    /// 對稱式加密類別(無法被繼承)。
    /// </summary>
    /// <remarks>本加解密類別是使用 UTF8 進行字串資料的轉換,當加密的資料是由 ASCII 或其他格式編碼,會造成資料無法正確解密。</remarks>
    public sealed class SymmetricCryptoUtility : IDisposable
    {
        /// <summary>
        /// 對稱式加密演算法物件。
        /// </summary>
        private readonly SymmetricAlgorithm Crypto = null;
        /// <summary>
        /// 演算法類型。
        /// </summary>
        private readonly SymmetricMode Mode;
        /// <summary>
        /// 對稱式加密類別建構式(無法被繼承)。
        /// </summary>
        /// <param name="algorithm">演算法類型。</param>
        public SymmetricCryptoUtility(SymmetricMode algorithm)
        {
            this.Mode = algorithm;

            switch (this.Mode)
            {
                case SymmetricMode.AES: this.Crypto = new AesCryptoServiceProvider(); break;
                case SymmetricMode.DES: this.Crypto = new DESCryptoServiceProvider(); break;
                case SymmetricMode.TripleDES: this.Crypto = new TripleDESCryptoServiceProvider(); break;
            }

            if (null == this.Crypto) throw new Exception();
        }
        /// <summary>
        /// 產生要用於該演算法的隨機初始化向量。
        /// </summary>
        /// <returns>向量字串。</returns>
        public string GenerateIV()
        {
            string szResult = String.Empty;

            this.Crypto.GenerateIV();

            szResult = Encoding.UTF8.GetString(this.Crypto.IV);

            return szResult;
        }
        /// <summary>
        /// 產生要用於演算法的隨機金鑰。
        /// </summary>
        /// <returns>金鑰字串。</returns>
        public string GenerateKey()
        {
            string szResult = String.Empty;

            this.Crypto.GenerateKey();

            szResult = Encoding.UTF8.GetString(this.Crypto.Key);

            return szResult;
        }
        /// <summary>
        /// 依據設定的演算法進行資料加密。
        /// </summary>
        /// <param name="originalString">原始未加密的字串。</param>
        /// <param name="key">金鑰字串</param>
        /// <param name="iv">向量字串</param>
        /// <returns>計算出來的加密位元組。</returns>
        public byte[] EncryptToBytes(string originalString, string key, string iv)
        {
            byte[] byResult = null;
            // Set Key and IV.
            this.Crypto.Key = Encoding.UTF8.GetBytes(key);
            this.Crypto.IV = Encoding.UTF8.GetBytes((this.Mode == SymmetricMode.AES ? iv : iv.Substring(0, 8)));
            // Encrypt a string to bytes.
            using (MemoryStream memoryStream = new MemoryStream())
            {
                ICryptoTransform cryptoTransform = null;

                switch (this.Mode)
                {
                    case SymmetricMode.AES: cryptoTransform = ((AesCryptoServiceProvider)this.Crypto).CreateEncryptor(); break;
                    case SymmetricMode.DES: cryptoTransform = ((DESCryptoServiceProvider)this.Crypto).CreateEncryptor(); break;
                    case SymmetricMode.TripleDES: cryptoTransform = ((TripleDESCryptoServiceProvider)this.Crypto).CreateEncryptor(); break;
                }

                using (CryptoStream encStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
                {
                    UTF8Encoding oUTF8 = new UTF8Encoding(false);

                    using (StreamWriter streamWriter = new StreamWriter(encStream, oUTF8))
                    {
                        // Write the originalValue to the stream.
                        streamWriter.Write(originalString);
                        // Close the StreamWriter.
                        streamWriter.Close();
                    }
                    // Close the CryptoStream.
                    encStream.Close();
                }
                // Get an array of bytes that represents the memory stream.
                byResult = memoryStream.ToArray();
                // Close the memory stream.
                memoryStream.Close();
            }
            // Return the encrypted string.
            return byResult;
        }
        /// <summary>
        /// 依據設定的演算法進行資料加密。
        /// </summary>
        /// <param name="originalString">原始未加密的字串。</param>
        /// <param name="key">金鑰字串。</param>
        /// <param name="iv">向量字串。</param>
        /// <returns>計算出來的加密字串。</returns>
        public string Encrypt(string originalString, string key, string iv)
        {
            string szResult = String.Empty;
            // Encrypt a string to bytes.
            byte[] byBuffer = this.EncryptToBytes(originalString, key, iv);
            // Convert to base 64 string.
            szResult = Convert.ToBase64String(byBuffer);
            // Return the encrypted string.
            return szResult;
        }
        /// <summary>
        /// 依據設定的演算法進行資料解密。
        /// </summary>
        /// <param name="encryptedBytes">被加密的位元組。</param>
        /// <param name="key">金鑰字串。</param>
        /// <param name="iv">向量字串。</param>
        /// <returns>原始的字串。</returns>
        public string DecryptFromBytes(byte[] encryptedBytes, string key, string iv)
        {
            string szResult = String.Empty;
            // Set Key and IV.
            this.Crypto.Key = Encoding.UTF8.GetBytes(key);
            this.Crypto.IV = Encoding.UTF8.GetBytes((this.Mode == SymmetricMode.AES ? iv : iv.Substring(0, 8)));
            // Create a memory stream to the passed buffer.
            using (MemoryStream memoryStream = new MemoryStream(encryptedBytes))
            {
                ICryptoTransform cryptoTransform = null;

                switch (this.Mode)
                {
                    case SymmetricMode.AES: cryptoTransform = ((AesCryptoServiceProvider)this.Crypto).CreateDecryptor(); break;
                    case SymmetricMode.DES: cryptoTransform = ((DESCryptoServiceProvider)this.Crypto).CreateDecryptor(); break;
                    case SymmetricMode.TripleDES: cryptoTransform = ((TripleDESCryptoServiceProvider)this.Crypto).CreateDecryptor(); break;
                }

                // Create a CryptoStream using the memory stream and the CSP DES key. 
                using (CryptoStream encStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Read))
                {
                    UTF8Encoding oUTF8 = new UTF8Encoding(false);

                    // Create a StreamReader for reading the stream.
                    using (StreamReader streamReader = new StreamReader(encStream, oUTF8))
                    {
                        // Read the stream as a string.
                        szResult = streamReader.ReadToEnd();
                        // Close the streams.
                        streamReader.Close();
                    }
                    // Close the CryptoStream.
                    encStream.Close();
                }
                // Close the memory stream.
                memoryStream.Close();
            }
            // Get padding character.
            int nPadding = Convert.ToInt32(szResult[szResult.Length - 1]);
            // Remove padding character for PHP.
            if (nPadding.Equals(4))
            {
                szResult = szResult.Substring(0, szResult.Length - nPadding);
            }
            // Return the decrypted string.
            return szResult;
        }
        /// <summary>
        /// 依據設定的演算法進行資料解密。
        /// </summary>
        /// <param name="encryptedString">被加密的字串。</param>
        /// <param name="key">金鑰字串。</param>
        /// <param name="iv">向量字串。</param>
        /// <returns>原始的字串。</returns>
        public string Decrypt(string encryptedString, string key, string iv)
        {
            string szResult = String.Empty;
            byte[] byBuffer = null;
            // Convert to an array of bytes.
            byBuffer = Convert.FromBase64String(encryptedString);
            // Decrypted bytes to original string.
            szResult = this.DecryptFromBytes(byBuffer, key, iv);
            // Return the decrypted string.
            return szResult;
        }
        /// <summary>
        /// 將 System.Security.Cryptography.AsymmetricAlgorithm 類別目前的執行個體所使用的資源全部釋出。
        /// </summary>
        public void Dispose()
        {
            this.Crypto.Clear();
            this.Crypto.Dispose();
        }
    }
}

Java 範例 (TripleDES):
package sample;

import javax.crypto.*;
import javax.crypto.spec.*;
import javax.xml.bind.DatatypeConverter;

/**
 * TripleDES 加解密服務的類別。
 * @author andychao
 */
public class TripleDES {
    private Cipher oCipher = null;
    private SecretKeySpec specKey = null;
    private IvParameterSpec specIV = null;
    
    public TripleDES(String key, String iv) throws Exception {
        // Create Instance.
        this.oCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        // Decode Key and IV.
        byte[] byKeys = key.getBytes("UTF-8");
        byte[] byIVs = iv.substring(0, 8).getBytes("UTF-8");
        // Duplicate Key the first 8 bytes of the key array.
        if (byKeys.length == 16) {
            byte[] byNewKeys = new byte[24];
            System.arraycopy(byKeys, 0, byNewKeys, 0, 16);
            System.arraycopy(byKeys, 0, byNewKeys, 16, 8);
            byKeys = byNewKeys;
        }
        // Restore Key and IV.
        this.specKey = new SecretKeySpec(byKeys, "DESede");
        this.specIV = new IvParameterSpec(byIVs);
    }
    
    public String Encrypt(String originalValue) throws Exception {
        // Declare variables.
        int nLength = 0;
        String szResult = null;
        // Initialize Cipher of TripleDES.
        this.oCipher.init(Cipher.ENCRYPT_MODE, this.specKey, this.specIV);
        // Convert original value to bytes.
        byte[] bySource = originalValue.getBytes("UTF-8");
        // Get output size for ciphers.
        byte[] byCiphers = new byte[this.oCipher.getOutputSize(bySource.length)];
        // Encrypt data.
        nLength = this.oCipher.update(bySource, 0, bySource.length, byCiphers, 0);
        nLength += this.oCipher.doFinal(byCiphers, nLength);
        // Convert to Base64 string.
        szResult = DatatypeConverter.printBase64Binary(byCiphers);
        // Return encrypted data.
        return szResult;
    }
    
    public String Decrypt(String encryptValue) throws Exception {
        // Declare variables.
        int nLength = 0;
        String szResult = null;
        // Decrypt string as bytes.
        byte[] byCiphers = DatatypeConverter.parseBase64Binary(encryptValue);
        // Initialize Cipher of TripleDES.
        this.oCipher.init(Cipher.DECRYPT_MODE, this.specKey, this.specIV);
        // Get output size for ciphers.
        byte[] bySource = new byte[this.oCipher.getOutputSize(byCiphers.length)];
        // Decrypt data.
        nLength = this.oCipher.update(byCiphers, 0, byCiphers.length, bySource, 0);
        nLength += this.oCipher.doFinal(bySource, nLength);
        // Convert bytes to string.
        szResult = new String(bySource, 0, bySource.length, "UTF-8");
        // Return Decrypted data.
        return szResult;
    }
}

Java 範例 (AES):
package sample;

import javax.crypto.*;
import javax.crypto.spec.*;
import javax.xml.bind.DatatypeConverter;
import java.security.*;

/**
 * AES 加解密服務的類別。
 * @author andychao
 */
public class AES {
    private Cipher oCipher = null;
    private SecretKeySpec specKey = null;
    private IvParameterSpec specIV = null;
    
    public AES(String key, String iv) throws Exception {
        // Create Instance.
        this.oCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        // Decode Key and IV.
        byte[] byKeys = key.getBytes("UTF-8");
        byte[] byIVs = iv.getBytes("UTF-8");
        // Restore Key and IV.
        this.specKey = new SecretKeySpec(byKeys, "AES");
        this.specIV = new IvParameterSpec(byIVs);
    }
    
    public String Encrypt(String originalValue) throws Exception {
        // Declare variables.
        int nLength = 0;
        String szResult = null;
        // Initialize Cipher of AES.
        this.oCipher.init(Cipher.ENCRYPT_MODE, this.specKey, this.specIV);
        // Convert original value to bytes.
        byte[] bySource = originalValue.getBytes("UTF-8");
        // Get output size for ciphers.
        byte[] byCiphers = new byte[this.oCipher.getOutputSize(bySource.length)];
        // Encrypt data.
        nLength = this.oCipher.update(bySource, 0, bySource.length, byCiphers, 0);
        nLength += this.oCipher.doFinal(byCiphers, nLength);
        // Convert to Base64 string.
        szResult = DatatypeConverter.printBase64Binary(byCiphers);
        // Return encrypted data.
        return szResult;
    }
    
    public String Decrypt(String encryptValue) throws Exception {
        // Declare variables.
        int nLength = 0;
        String szResult = null;
        // Decrypt string as bytes.
        byte[] byCiphers = DatatypeConverter.parseBase64Binary(encryptValue);
        // Initialize Cipher of AES.
        this.oCipher.init(Cipher.DECRYPT_MODE, this.specKey, this.specIV);
        // Get output size for ciphers.
        byte[] bySource = new byte[this.oCipher.getOutputSize(byCiphers.length)];
        // Decrypt data.
        nLength = this.oCipher.update(byCiphers, 0, byCiphers.length, bySource, 0);
        nLength += this.oCipher.doFinal(bySource, nLength);
        // Convert bytes to string.
        szResult = new String(bySource, 0, bySource.length, "UTF-8");
        // Return Decrypted data.
        return szResult;
    }
}

PHP 範例 (TripleDES):
/**
 * TripleDES 加解密服務的類別。
 */
class TripleDES {

    private $Key = '1234567890';
    private $IV = '1234567890';
    /**
     * TripleDES 加解密服務類別的建構式。
     */
    function __construct($key, $iv) {
        $this->TripleDES($key, $iv);
    }
    /**
     * TripleDES 加解密服務類別的實體。
     */
    function TripleDES($key, $iv) {
        $this->Key = substr($key . $key, 0, 24);
        $this->IV = substr($iv, 0, 8);
    }
    /**
     * 加密服務的方法。
     */
    function Encrypt($data)
    {
        $szBlockSize = mcrypt_get_block_size(MCRYPT_TRIPLEDES, MCRYPT_MODE_CBC);
        $szPad = $szBlockSize - (strlen($data) % $szBlockSize);
        $szData = mcrypt_encrypt(MCRYPT_TRIPLEDES, $this->Key, $data. str_repeat(chr($szPad), $szPad), MCRYPT_MODE_CBC, $this->IV);
        $szData = base64_encode($szData);

        return $szData;
    }
    /**
     * 解密服務的方法。
     */
    function Decrypt($data)
    {
        $szValue = base64_decode($data);
        $szValue = mcrypt_decrypt(MCRYPT_TRIPLEDES, $this->Key, $szValue, MCRYPT_MODE_CBC, $this->IV);
        $nLength = strlen($szValue);
        $nPadding = ord($szValue[$nLength - 1]);
        $szValue = substr($szValue, 0, $nLength - $nPadding);

        return $szValue;
    }
}

PHP 範例 (AES):
/**
 * AES 加解密服務的類別。
 */
class AES {

    private $Key = '1234567890';
    private $IV = '1234567890';
    /**
     * AES 加解密服務類別的建構式。
     */
    function __construct($key, $iv) {
        $this->AES($key, $iv);
    }
    /**
     * AES 加解密服務類別的實體。
     */
    function AES($key, $iv) {
        $this->Key = $key;
        $this->IV = $iv;
    }
    /**
     * 加密服務的方法。
     */
    function Encrypt($data)
    {
        $szBlockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        $szPad = $szBlockSize - (strlen($data) % $szBlockSize);
        $szData = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->Key, $data. str_repeat(chr($szPad), $szPad), MCRYPT_MODE_CBC, $this->IV);
        $szData = base64_encode($szData);

        return $szData;
    }
    /**
     * 解密服務的方法。
     */
    function Decrypt($data)
    {
        $szValue = base64_decode($data);
        $szValue = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->Key, $szValue, MCRYPT_MODE_CBC, $this->IV);
        $nLength = strlen($szValue);
        $nPadding = ord($szValue[$nLength - 1]);
        $szValue = substr($szValue, 0, $nLength - $nPadding);

        return $szValue;
    }
}

Delphi 範例 (AES Ref. kuraki5336 網誌):
{ TODO: xStr 明文, xKey 加密金鑰 xIV 加密向量 }
function EncryAES(xStr, xKey, xIV: AnsiString): String;
var
    Source: TStringStream;
    Dest: TStringStream;
    { TODO: 引用 ELAES.PAS 就會認識了 }
    mKey: TAESKey128;
    mIV: TAESBuffer;
    strRemainder, i: Integer;
    mstr, aKey, aIV: Ansistring;
begin
    try
        { TODO: 不要覺得奇怪,不這樣重給,值就是會不對  } 
        { TODO: ※我外部傳入其實已經是ANSISTING了不知道為什麼直接使用上面的xStr xKey 這載入的值就會有異常。因此從新給一次※ } 
        mstr := xStr;
        aKey := xKey;
        aIV :=xIV;
        { TODO: pksc5  PHP 是用pksc5 但是DELPHI & JAVA 就是要用pksc5才會對  }
        { TODO: ※補位的主要原因是在   EncryptAESStreamCBC 會檢核你輸入的數值是否有達到128K 192K 248K 因此來源值需要補位※ } 
        strRemainder :=Length(mstr) mod 16;
        strRemainder := 16 - strRemainder;
        for i := 1 to strRemainder do
        begin
            mstr := mstr + Chr(strRemainder);
        end;
        { TODO: KEY & IV 將KEY轉成Array of Byte }
        FillChar( mKey, SizeOf(mKey), #0 );
        Move( PAnsiChar(aKey)^, mKey, 16);
        FillChar( mIV, SizeOf(mIV), #0 );
        Move( PAnsiChar(aIV)^, mIV, 16);
        { TODO: Input & output 並賦予值 }
        Source := TStringStream.Create(mstr, 65001);
        Dest   := TStringStream.Create('', 65001);
        { TODO: 加密 }
        EncryptAESStreamCBC( Source, 0, mKey, mIV, Dest );
        { TODO: BASE64 千萬不要對Dest做任何的變化,保持BYTE來做加解密}
        Result := EncodeBase64(Dest.Bytes, Dest.size);
    finally
        Source.Free;
        Dest.Free;
    end;
end;

{ TODO: 再回傳上有一組資訊是被加密過得因此我們必須解密才能得到裡面的值做紀錄 }
{ TODO: xStr的值會是ALLPAY回應給我們的加密電文 , 因此要按照當初加密的方式反向解密 }
function DecryptAES(xStr, xKey, xIV: AnsiString): String;
var
    Source: TStringStream;
    Dest: TStringStream;
    mKey: TAESKey128;
    mIV: TAESBuffer;
    strRemainder,i:Integer;
    mstr,aKey,aIV:Ansistring;
    mBytes, mReturnByte :TBytes;
begin
    try
        { TODO: Input & output }
        Dest := TStringStream.Create('', 65001);
        Source := TStringStream.Create('', 65001);
        { TODO: 不要覺得奇怪,不這樣重給,值就是會不對 } 
        mstr := xStr;
        aKey := xKey;
        aIV := xIV;
        { TODO: 反解密.DecodeBase64 }
        mBytes := DecodeBase64(mstr);
        { TODO: 將資料已Byte方式輸入...千千萬萬不要.....拿字串輸入哦 }
        { TODO: 不可以這樣寫 Source.WriteBuffer(mBytes, mBytes.size); 寫進去的值根本不對。我不知道為什麼@@ }
        Source.Position := 0;
        for i := 0 to length(mBytes) -1 do
        begin
            Source.WriteBuffer(mBytes[i], 1);
        end;
        { TODO: 不用補位 }
        { TODO: KEY & IV 將KEY轉成Array of Byte }
        FillChar( mKey, SizeOf(mKey), #0 );
        Move( PAnsiChar(aKey)^, mKey, 16);
        FillChar( mIV, SizeOf(mIV), #0 );
        Move( PAnsiChar(aIV)^, mIV, 16);
        { TODO: 解密 }
        DecryptAESStreamCBC( Source, 0, mKey, mIV, Dest );
        { TODO: 濾掉byte < 32 --小於32的都是特殊字元對於解析無意義}
        Dest.Position := 0;
        SetLength(mReturnByte, Dest.size);
        for i := 0 to Dest.size do
        begin
           if (Dest.Bytes[i] <= 32) then
              continue;
           Dest.Read(mReturnByte[i], 1);
        end;
        { TODO: 轉字串 }
        Result := Dest.DataString;
    finally
        Source.Free;
        Dest.Free;
    end;
end;

以上的範例,

眼尖的朋友會發現,

為什麼其他語言都是 PKCS5,

而 .NET 是使用 PKCS7,

但是加解密是可以互通的呢?!

原因是 PKCS5 與 PKCS7 裡使用的填補演算法是相同~~


就醬~打完收工~~


在 Blogger 使用 Google Code Prettify 程式碼美化區塊筆記

Google Code Prettify 是一個簡單易用的程式碼高亮度顯示程式。
  • 支援支援多種程式語言
  • 僅需載入一個檔案
  • 可以自訂修改樣式

以下簡單示範如何在 Blogger 設定使用 Google Code Prettify。


Step 1: 加入 Google Code Prettify 語法支援設定

請先到網誌的版面配置頁面,如下圖:


拉到該畫面最下方,選擇任意一個新增小工具。


選擇加入 HTML/JavaScript 小工具。


在小工具中打上標題,在內容中貼上程式碼,並按下儲存按鈕,這樣就完成了設定。如下程式碼與圖例:
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>



Step 2: 在文章中貼上程式碼

在撰寫新文章時選擇 HTML方式撰寫程式碼。


接著在撰寫網誌原始碼的地方以 <pre> 標籤範圍內撰寫或貼上程式碼。如下:
<pre class="prettyprint">
<code class="language-html">
你的程式碼...
</code>
</pre>

要特別注意的是,如果程式碼有 "&"、"<"、">" 這三個符號,需將 "&" 轉換為 "&amp;"、"<" 轉換為 "&lt;"、">" 轉換為 "&gt;";若覺得麻煩,也可使用些線上轉換的小工具 Online HTML Encode/Decode 轉換完後再貼上。


Step 3: 變更程式碼顯示樣式

Google Code Prettify 提供幾個程式碼的顯示樣式(Skin Gallery),只要回到 HTML/JavaScript 小工具,編輯原本貼上的程式碼,加上 skin 參數,並指定想顯示的 skin 名稱即可。使用方式如下:
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?skin=desert"></script>

如果想在程式碼區塊顯示行號,需要在 <pre> 標籤的 class 屬性中加入 linenums 的樣式,如下:
<pre class="prettyprint linenums">
<code class="language-html">
你的程式碼...
</code>
</pre>

若想要在程式碼區塊的每一行都顯示行號,可以在 HTML/JavaScript 小工具加入以下 CSS 程式碼:
<style type="text/css">
li.L0, li.L1, li.L2, li.L3, li.L5, li.L6, li.L7, li.L8 { list-style-type: decimal !important }
</style>

如果 Google Code Prettify 的樣式你不喜歡,而你也很熟悉 CSS,也可以參考 Google Code Prettify 提供的樣式進行些微調。

就醬囉~