如何在LabVIEW中实现AES加解密并配置如下设置?
- Padding = PaddingMode.PKCS7
- 模式 = CipherMode.CBC
- key 大小 = 128
- block 大小 = 128
我在这里尝试了几个选项 Igor Titov , AES Crypto Toolkit by Alab Technologies 试图联系双方以确认这些工具包是否支持上述配置,但他们没有通过电话或电子邮件回复。 非常感谢任何帮助。
我从 Igor Titov 找到了这段代码
/**
* 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;
}
/**
* 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 片段。
最佳答案
我对河豚做了类似的事情,但不熟悉 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
这听起来相对简单,下面的简单框图显示了它的工作原理:
关于c# - NI LabVIEW 中的 AES 加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51946325/