NI LabView中的AES加密

时间:2018-08-21 10:08:23

标签: c# aes labview

如何在LabView中实现AES加密和解密并配置以下设置?

  1. 填充= PaddingMode.PKCS7
  2. Mode = CipherMode.CBC
  3. 密钥大小= 128
  4. 块大小= 128

我在这里Igor TitovAES Crypto Toolkit by Alab Technologies尝试了很少的选择 试图与双方确认这些工具包是否支持上述配置,但它们不会通过电话或电子邮件进行响应。 任何帮助表示赞赏。

我在Igor Titov

中找到了此代码

加密:https://github.com/IgorTitov/LabVIEW-Advanced-Encryption-Standard/blob/master/Encrypt%20with%20AES.vi

/** 
     * Encrypt a text using AES encryption in Counter mode of operation
     *
     * Unicode multi-byte character safe
     *
     * @param plaintext Source text to be encrypted
     * @param password  The password to use to generate a key
     * @param nBits     Number of bits to be used in the key (128, 192, or 256)
     * @returns         Encrypted text
     */


    public function encrypt(plaintext : String, password : String, nBits : int) : String //Done in LV
    {
           var blockSize : int = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
        if (!(nBits == BIT_KEY_128 || nBits == BIT_KEY_192 || nBits == BIT_KEY_256)) 
  {
                 // standard allows 128/192/256 bit keys
              throw new Error("Must be a key mode of either 128, 192, 256 bits");
        }
        plaintext = Utf8.encode(plaintext);
        password = Utf8.encode(password);

        // use AES itself to encrypt password to get cipher key (using plain password as source for key 
        // expansion) - gives us well encrypted key
        var nBytes : int = nBits / 8;  // no bytes in key
        var pwBytes : Array = new Array(nBytes);
        for (var i : int = 0;i < nBytes;i++) 
        {
               pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i);
        }
        var key : Array = cipher(pwBytes, keyExpansion(pwBytes));  // gives us 16-byte key

        key = key.concat(key.slice(0, nBytes - 16));  // expand key to 16/24/32 bytes long

        // initialise counter block (NIST SP800-38A §B.2): millisecond time-stamp for nonce in 1st 8 bytes,
        // block counter in 2nd 8 bytes
        var counterBlock : Array = new Array(blockSize);
        var nonce : int = 123456789;////DEBUG!!!(new Date()).getTime();  // timestamp: milliseconds since 1-Jan-1970
        var nonceSec : int = Math.floor(nonce / 1000);
        var nonceMs : int = nonce % 1000;

        // encode nonce with seconds in 1st 4 bytes, and (repeated) ms part filling 2nd 4 bytes
        for (i = 0;i < 4;i++) 
        {
               counterBlock[i] = (nonceSec >>> (i * 8)) & 0xff;             
        }

        for (i = 0;i < 4;i++)
        {
               counterBlock[i + 4] = nonceMs & 0xff;
        } 
        // and convert it to a string to go on the front of the ciphertext
        var ctrTxt : String = '';
        for (i = 0;i < 8;i++) 
        {
               ctrTxt += String.fromCharCode(counterBlock[i]);
        }
        // generate key schedule - an expansion of the key into distinct Key Rounds for each round
        var keySchedule : Array = keyExpansion(key);
        var blockCount : int = Math.ceil(plaintext.length / blockSize);
        var ciphertxt : Array = new Array(blockCount);  // ciphertext as array of strings

        for (var b : int = 0;b < blockCount;b++) 
        {
               // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
               // done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
               for (var c : int = 0;c < 4;c++) 
            {
                    counterBlock[15 - c] = (b >>> (c * 8)) & 0xff;                  
        }

            for (c = 0;c < 4;c++) 
            {
                    counterBlock[15 - c - 4] = (b / 0x100000000 >>> c * 8);
            }

            var cipherCntr : Array = cipher(counterBlock, keySchedule);  // -- encrypt counter block --

            // block size is reduced on final block
            var blockLength : int = b < blockCount - 1 ? blockSize : (plaintext.length - 1) % blockSize + 1;
            var cipherChar : Array = new Array(blockLength);

            for (i = 0;i < blockLength;i++) 
            {  
                // -- xor plaintext with ciphered counter char-by-char --
                cipherChar[i] = cipherCntr[i] ^ plaintext.charCodeAt(b * blockSize + i);                    
                //trace("i=",i,"plaintext.charCodeAt(b * blockSize + i)",plaintext.charCodeAt(b * blockSize + i),"cipherChar[i]=",cipherChar[i]);
                cipherChar[i] = String.fromCharCode(cipherChar[i]);

            }

            ciphertxt[b] = cipherChar.join(''); 
            //trace(ciphertxt);
        }

        // Array.join is more efficient than repeated string concatenation in IE
        var ciphertext : String = ctrTxt + ciphertxt.join('');
        //trace("before 64 encode:",ciphertext);
        ciphertext = Base64.encode(ciphertext);  // encode in base64
           //trace("after 64 encode:",ciphertext);
           //alert((new Date()) - t);

        return ciphertext;
    }

解密:https://github.com/IgorTitov/LabVIEW-Advanced-Encryption-Standard/blob/master/Decrypt%20with%20AES.vi

/** 
         * Decrypt a text encrypted by AES in counter mode of operation
         *
         * @param ciphertext Source text to be encrypted
         * @param password   The password to use to generate a key
         * @param nBits      Number of bits to be used in the key (128, 192, or 256)
         * @returns          Decrypted text
         */
        public function decrypt(ciphertext : String, password : String, nBits : int) : String 
  {
            var blockSize : int = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
            if (!(nBits == BIT_KEY_128 || nBits == BIT_KEY_192 || nBits == BIT_KEY_256)) {
                  // standard allows 128/192/256 bit keys
                  throw new Error("Must be a key mode of either 128, 192, 256 bits");
            }

            ciphertext = Base64.decode(ciphertext.split("\n").join(""));
            password = Utf8.encode(password);
            //var t = new Date();  // timer

            // use AES to encrypt password (mirroring encrypt routine)
            var nBytes : int = nBits / 8;  // no bytes in key
            var pwBytes : Array = new Array(nBytes);
            for (var i : int = 0;i < nBytes;i++) 
            {
                pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i);
            }
            var key : Array = cipher(pwBytes, keyExpansion(pwBytes));
            key = key.concat(key.slice(0, nBytes - 16));  // expand key to 16/24/32 bytes long

            // recover nonce from 1st 8 bytes of ciphertext
            var counterBlock : Array = new Array(8);
            var ctrTxt : String = ciphertext.slice(0, 8);
            for (i = 0;i < 8;i++) 
            {
                counterBlock[i] = ctrTxt.charCodeAt(i);
            }

            // generate key schedule
            var keySchedule : Array = keyExpansion(key);

            // separate ciphertext into blocks (skipping past initial 8 bytes)
            var nBlocks : int = Math.ceil((ciphertext.length - 8) / blockSize);
            var ct : Array = new Array(nBlocks);
            for (b = 0;b < nBlocks;b++) 
            {
                ct[b] = ciphertext.slice(8 + b * blockSize, 8 + b * blockSize + blockSize);

                //trace("ct[b]=",ct[b],"blockSize=",blockSize,8 + b * blockSize, 8 + b * blockSize + blockSize);
            }
            //var temp:String=ct[1];
//          for (var i:int=0;i<temp.length;i++)
//          {
//              trace("ct[1]Byte Array:",temp.charCodeAt(i));
//          }

            var ciphertextArr : Array = ct;  // ciphertext is now array of block-length strings

            // plaintext will get generated block-by-block into array of block-length strings
            var plaintxt : Array = new Array(ciphertextArr.length);

            for (var b : int = 0;b < nBlocks;b++) 
            {
                // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
                for (var c : int = 0;c < 4;c++) 
                   {
                        counterBlock[15 - c] = ((b) >>> c * 8) & 0xff;
                }
                for (c = 0;c < 4;c++) 
                {
                        counterBlock[15 - c - 4] = (((b + 1) / 0x100000000 - 1) >>> c * 8) & 0xff;
                }
                //trace(counterBlock);
                var cipherCntr : Array = cipher(counterBlock, keySchedule);  // encrypt counter block
                //trace(cipherCntr);
                var plaintxtByte : Array = new Array(String(ciphertextArr[b]).length);
                for (i = 0;i < String(ciphertextArr[b]).length;i++) 
                {
                    // -- xor plaintxt with ciphered counter byte-by-byte --
                    plaintxtByte[i] = cipherCntr[i] ^ String(ciphertextArr[b]).charCodeAt(i);
                    //trace("i=",i,"plaintxtByte[i]=",plaintxtByte[i],"cipherCntr[i]=",cipherCntr[i],"String(ciphertextArr[b]).charCodeAt(i)=",String(ciphertextArr[b]).charCodeAt(i));
                    //trace(plaintxtByte[i]);
                    plaintxtByte[i] = String.fromCharCode(plaintxtByte[i]);

                }
                plaintxt[b] = plaintxtByte.join('');
            }

            // join array of blocks into single plaintext string
            var plaintext : String = plaintxt.join('');
            plaintext = Utf8.decode(plaintext);  // decode from UTF8 back to Unicode multi-byte chars
            return plaintext;
        }

不确定这是什么编程语言。如果我在将这段代码转换为C#方面能获得帮助,它将解决我的阻止程序。

这是VI中的代码

enter image description here

1 个答案:

答案 0 :(得分:0)

我对河豚做了类似的事情,但是对Alab Tech的AES实现并不熟悉。
假设Alab Tech库功能正常,则在加密数据之前,只需填充数据即可。

  

KCS7(在RFC 5652中描述)。这会将数据填充到块大小   等于已添加字节数的数字。如果原来   数据是N个字节的整数倍,然后是一个额外的字节块   加上N值

这听起来相对简单,下面的简单框图显示了其工作方式:

enter image description here