我试图加密动态QRCode的数据有效负载。
我们有一个应用程序,可以根据动态数据生成QRCode,如果需要,我们希望有一个加密有效负载的选项。
由于QRCodes固有的大小限制,其中一个要求是有效负载数据必须与加密数据的大小相同。如果加密数据不同/太大,QRCode可能无法正确扫描/解码。
我尝试在CTR模式下使用AES加密(流而不是阻止),如其他地方所建议的那样。结果是输出密码字节与输入字节大小相同,但是将字节转换为char友好格式(例如base64)会产生比原始有效负载长得多的字符串长度。
是否可以加密字符串以使纯文本和加密字符串长度相同?
根据这个位于https://courses.csail.mit.edu/6.857/2014/files/12-peng-sanabria-wu-zhu-qr-codes.pdf的麻省理工学院pdf,他们提到了现有的解决方案,他们称之为SEQR(对称加密QR)代码。但是,我还没有找到一个解决方案,如本文所述,它产生的加密输出与纯文本输入的长度相同。
我们在我们的后端使用C#.NET,在我们的前端使用ZXing QRCode库和Javascript,使用CryptoJS。
我还在CTR模式下创建了一个JSFiddle演示AES。
http://jsfiddle.net/s1jeweja/5/
var options = { mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding };
/*** encrypt */
var json = CryptoJS.AES.encrypt("some plain text", "secret", options);
var ciphertext = json.ciphertext.toString(CryptoJS.enc.UTF8);
document.getElementById("id2").innerHTML = ciphertext;
//debugger;
/*** decrypt */
var decrypted = CryptoJS.AES.decrypt(json, "secret", options);
var plaintext = decrypted.toString(CryptoJS.enc.Utf8);
document.getElementById("decrypt").innerHTML = plaintext; // text can be a random lenght
答案 0 :(得分:1)
您正在寻找将明文文本字符转换为密文文本字符的Format Preserving Encryption。一种方法是改编经典Vigenère cipher。生成0..25范围内的伪随机数密钥流,并使用它们对字母表周围的明文字符进行循环移位。
您已使用AES-CTR,因此请使用它来生成密钥流。掩盖密钥流的五位。如果这5位在0..25中,则使用它们将下一个明文字符循环移位到相应的密文字符。如果五位在26..31范围内,则丢弃它们并获得另外五位。
在伪代码中,这看起来像:
textToTextEncode(plaintext)
for each character p in plaintext
c <- p + getNextShift()
if c > 'z'
c <- c - 26
end if
write(c, cyphertextFile)
end for
end textToTextEncode()
getNextShift()
repeat
b <- getNextByte(AES-CTR)
b <- b & 0b00011111 // Binary mask.
until b < 26
return b
end getNextShift()
对于解密,您需要减去班次值,如果结果低于&#39; a,则需要加26。
ETA:从下面的评论中可以看出,您需要一个对每个QRCode都唯一的随机数(AKA IV)。在每个QRCode的开始或结束处为nonce留出固定数量的字节。不要加密那些字节,你必须把它们留在明文中。从完整的QRCode中提取它们并使用它们初始化您的AES-CTR方法。然后使用该AES-CTR解密其余的QRCode。字节越多,最多16个,您的安全性就越高。
答案 1 :(得分:1)
据我所知,输入类型的限制必须是一个字符串,或多或少具有历史性,并且在过去从未改变过。无论条形码格式是否有可能对字节数据进行编码。
这是一个适合我的小代码片段:
[Test]
public void Test_Binary_Data_Encoding_As_Char()
{
var writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new QrCodeEncodingOptions
{
ErrorCorrection = ErrorCorrectionLevel.L,
CharacterSet = "ISO-8859-1"
}
};
// Generate dummy binary data
var binaryData = new byte[256];
for (var i = 0; i < binaryData.Length; i++)
binaryData[i] = (byte)i;
// Convert the dummy binary data to a string
var binaryDataAsChar = new char[binaryData.Length];
for (var i = 0; i < binaryDataAsChar.Length; i++)
binaryDataAsChar[i] = (char)binaryData[i];
var binaryDataAsString = new String(binaryDataAsChar);
// encode the string as QR code
var qrcode = writer.Write(binaryDataAsString);
// decode the QR code (full roundtrip test)
var reader = new BarcodeReader();
var binaryDataAsStringFromQrCode = reader.Decode(qrcode);
var binaryDataAsStringFromQrCodeText = binaryDataAsStringFromQrCode.Text;
// a little hack, because the barcode reader converts the \n to \r\n
binaryDataAsStringFromQrCodeText = binaryDataAsStringFromQrCodeText.Remove(10, 1);
// convert the result string to the byte array
var binaryDataFromQrCode = new byte[256];
for (var i = 0; i < binaryDataFromQrCode.Length; i++)
binaryDataFromQrCode[i] = (byte)binaryDataAsStringFromQrCodeText[i];
// Assert, that the representation of the result string and the byte array is equal to the source
Assert.That(binaryDataAsString, Is.EqualTo(binaryDataAsStringFromQrCodeText));
for (var i = 0; i < binaryData.Length; i++)
Assert.That(binaryDataFromQrCode[i], Is.EqualTo(binaryData[i]), "position " + i + " is wrong");
}