2017-07-31 4 views
1

動的QRCodeのデータペイロードを暗号化しようとしています。出力長と同じ入力長でQRCodeペイロードを暗号化します

私たちは動的データからQRコードを生成するアプリを持っており、必要に応じてペイロードを暗号化するオプションが必要です。

はQRCodesに固有のサイズ制限のため、要件の1つは、ペイロードデータ暗号化データと同じサイズでなければならないことです。暗号化されたデータが異なる/大きすぎると、QRCodeが正しくスキャン/デコードできないことがあります。

私は、他の場所で提案されているように、CTRモード(ブロックとは対照的にストリーム)でAES暗号化を使用しようとしました。その結果、出力暗号バイトは入力バイトと同じサイズになりますが、バイトをcharフレンドリ形式(たとえばbase64)に変換すると元のペイロードよりもはるかに長い文字列長が生成されます。

プレーンテキストと暗号化された文字列の長さが同じになるように文字列を暗号化する方法はありますか?

ここにあるhttps://courses.csail.mit.edu/6.857/2014/files/12-peng-sanabria-wu-zhu-qr-codes.pdfにあるこのMIT pdfによれば、彼らはSEQR(Symmetric Encrypted QR)コードと呼ばれる既存のソリューションを挙げています。しかし、私はまだ記事で述べたように、同じ長さのプレーンテキスト入力が暗号化された出力を生成する解決策を見つけることはできません。

私たちはバックエンドでC#.NET、フロントエンドにZXing QRCodeライブラリとJavascript、CryptoJSを使用しています。

また、CTRモードでAESをデモストするJSFiddleも作成しました。

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

QRコードは、生のバイナリデータを搬送する困難はありません。平文と正確に同じサイズのペイロードを暗号化するのが本当に安全かどうかを検討するべきだとも思います。たとえば、あなたのシステムが[再生攻撃](https://en.wikipedia.org/wiki/Replay_attack)に対して脆弱であることが重要ですか? –

+0

私は、ペイロードをバイナリとして格納することはオプションではないという印象を受けていましたが、私はこれを再訪します。 あなたは脆弱性のリスクについては正しいですか。コンテキスト:私たちは、個人情報をQRコードに保存し、イベント用に印刷しています。他の出席者が出席者の許可なく出席者情報を収集するのを防ぐことが重要です。誰かが何らかの形ですべての出席者の物理的なQRコードを収集してから脆弱性を利用すると、この種の情報を簡単に収穫できる方法があると思います。私はそれが受け入れられるリスクだと思うでしょう – gorillapower

答えて

1

あなたは、テキスト文字を暗号文平文テキスト文字を変換しFormat Preserving Encryptionを探しています。それを行う1つの方法は古典的なVigenère cipherの適応です。疑似乱数のキーストリームを0..25の範囲で生成し、アルファベットのまわりの平文文字の循環シフトを行うためにそれらを使用します。

すでにAES-CTRを使用していますので、これを使用してキーストリームを生成してください。キーストリームの5ビットをマスクします。これらの5つのビットが0..25にある場合、それらを使用して、次の平文文字の対応する暗号文文字への巡回シフトを行います。 5つのビットが26..31の範囲内にある場合、それらを破棄して別の5ビットを得る。擬似コードで

、このようなものになります。あなたがシフト値を減算し、結果は「A」を下回る場合は26を追加する必要があります解読のために

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() 

を。

ETA:以下のコメントからわかるように、各QRコードに固有のナンス(AKA IV)が必要です。ノンスの各QRCodeの先頭または末尾に固定数のバイトを確保します。これらのバイトを暗号化しないでください。クリアにしておく必要があります。完全なQRコードからそれらを抽出し、それらを使用してAES-CTRメソッドを初期化します。その後、そのAES-CTRを使用して、そのQRコードの残りの部分を復号化します。より多くのバイト、16まで、より多くのセキュリティがあります。

+0

これは全く安全ではありません。 Donald Trumpがイベントに出席し、彼の名前が 'TKRREB NZIBP'として暗号化されているQRコードを受け取ったとします。彼はこの情報から直接キーストリームを抽出し、それを使って他の名前、例えば「RWVRVI IJOBA」=バラクオバマを解読することができる。 –

+0

AES-CTRにはセキュリティのためのノンスが必要です。質問者が提供したコードの 'options'パラメータの一部。 – rossum

+0

はい、OPは暗号文が平文と同じサイズであることをOPが要求しているため、IVまたはノンスはありません。 –

1

私が知る限り、文字列でなければならない入力の種類の制限は多かれ少なかれ過去のものであり、決して変更されていません。バイトデータをエンコードするための異なるバーコードフォーマットの可能性にかかわらず。ここで

は、私の作品の小さなコードスニペットです:「CHARやさしい」ペイロードのための要件は任意と逆効果と思われるので、

[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"); 
    } 
関連する問題