c# - NI LabVIEW 中的 AES 加密

标签 c# aes labview

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

  1. Padding = PaddingMode.PKCS7
  2. 模式 = CipherMode.CBC
  3. key 大小 = 128
  4. block 大小 = 128

我在这里尝试了几个选项 Igor Titov , AES 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

最佳答案

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

KCS7 (described in RFC 5652). This pads data to the blocksize with the number that is equal to the number of added bytes. If the original data is an integer multiple of N bytes, then an extra block of bytes with value N is added

这听起来相对简单,下面的简单框图显示了它的工作原理:

enter image description here

关于c# - NI LabVIEW 中的 AES 加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51946325/

相关文章:

c# - 使用setTimeout在javascript中倒数计时器

c# - If 语句逻辑和数组

c# - 你能从没有参数的属性中省略括号吗?

python - PyDAQmx 或类似软件适用于 Mac 吗?

mysql - 来自八个表的多个 JOIN 和 SELECT 语句

为 Labview 创建 DLL

c# - 如何提取列表中具有相同值的项目数?

c++ - 流转换过滤器 : invalid PKCS #7 block padding found in AES decryption

java - 如何将 AES CCM 与 BouncycaSTLe JCE 提供程序一起使用 - CCMParameters

C# AES 算法 - 我应该在哪里以及如何存储 key 和 IV