C# 使用与输出长度相同的输入长度加密QRCode有效负载

C# 使用与输出长度相同的输入长度加密QRCode有效负载,c#,cryptography,aes,qr-code,cryptojs,C#,Cryptography,Aes,Qr Code,Cryptojs,我正在尝试加密动态QRCode的数据负载 我们有一个从动态数据生成QRCode的应用程序,如果需要,我们希望有一个选项来加密有效负载 由于QR码固有的大小限制,其中一项要求是有效负载数据必须与加密数据的大小相同。如果加密数据不同/太大,QRCode可能无法正确扫描/解码 我曾尝试在CTR模式下使用AES加密(流而不是块),正如其他地方所建议的那样。结果是,输出密码字节的大小与输入字节的大小相同,但是将字节转换为字符友好格式(例如base64)会产生比原始有效负载长得多的字符串长度 有没有办法加密

我正在尝试加密动态QRCode的数据负载

我们有一个从动态数据生成QRCode的应用程序,如果需要,我们希望有一个选项来加密有效负载

由于QR码固有的大小限制,其中一项要求是有效负载数据必须与加密数据的大小相同。如果加密数据不同/太大,QRCode可能无法正确扫描/解码

我曾尝试在CTR模式下使用AES加密(流而不是块),正如其他地方所建议的那样。结果是,输出密码字节的大小与输入字节的大小相同,但是将字节转换为字符友好格式(例如base64)会产生比原始有效负载长得多的字符串长度

有没有办法加密字符串,使纯文本和加密字符串长度相同

根据这里的麻省理工学院pdf,他们提到了已经存在的解决方案,他们称之为SEQR(对称加密QR)码。然而,我还没有找到一个解决方案,正如文章中提到的,它会产生与纯文本输入长度相同的加密输出

我们在后端使用C#NET,在前端使用ZXing QRCode库和Javascript,并使用CryptoJS

我还创建了一个JSFIDLE,在CTR模式下演示AES

您正在寻找将明文字符转换为密码文本字符的。一种方法是改编经典。生成范围为0..25的伪随机数的密钥流,并使用它们对字母表中的明文字符进行循环移位

您已经在使用AES-CTR,所以请使用它来生成密钥流。屏蔽掉密钥流的五位。如果这五位在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()
texttotexncode(纯文本)
对于明文中的每个字符p
c'z'

据我所知,输入类型必须是字符串的限制或多或少是历史性的,过去从未改变过。不管是否可能使用不同的条形码格式对字节数据进行编码

下面是一个适用于我的小代码片段:

  [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");
  }
[测试]
公共无效测试\u二进制\u数据\u编码\u为\u字符()
{
var writer=新条形码编写器
{
格式=条形码格式.QR\U代码,
选项=新的QRCODE编码选项
{
ErrorCorrection=ErrorCorrectionLevel.L,
CharacterSet=“ISO-8859-1”
}
};
//生成虚拟二进制数据
var binaryData=新字节[256];
对于(var i=0;i
QR码在传输原始二进制数据方面没有困难,因此对“字符友好”有效载荷的要求似乎是任意的,而且适得其反。我也认为你应该考虑是否有真正的安全的加密有效载荷的大小相同的明文。例如,您的系统易受攻击有关系吗?我的印象是,将有效负载存储为二进制不是一个选项,我将重新讨论这个问题。关于脆弱性风险,你是对的。上下文:我们正在QRCode中存储个人信息,并为事件打印这些信息。更重要的是防止其他与会者在未经其许可的情况下收集与会者信息。如果有人以某种方式收集所有与会者的物理QR码,然后利用一个漏洞,我认为会有更简单的方法获取此类信息吗?我认为这是一个可以接受的风险,这根本不安全。假设唐纳德·特朗普出席活动并收到一个二维码,其中他的名字被加密为
Tkreb NZIBP
。然后,他可以直接从该信息中提取密钥流,并可以使用它来解密任何其他名称,例如,
RWVRVI IJOBA
=Barack Obama。AES-CTR需要一个临时密码以确保安全。提问者提供的代码的
选项
参数的一部分。安全加密总是有附加信息:密钥、IV/nonce等。是的,但OP要求密文与明文大小相同,因此没有任何IV或nonce。或密钥?如果没有额外信息,您无法正确使用AES-CTR。因此请不要。(是的,你当然需要钥匙,但是你
  [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");
  }