先看:
將其中一個圖更改透明度為50%,重疊兩張圖後:
源於:http://leemon.com/crypto/VisualCrypto.html
大家可以先去看看,作者的意思是,甲乙兩方需要傳遞訊息,可以事先說好密鑰,傳遞訊息時只要給其發送stream(明文)圖片即可,另一方解密,只需輸入密鑰和相應的訊息長度(輸入等量空格)即可得到ciphertext(密鑰)圖片,最終得到訊息內容。同一張密鑰圖片可以匹配多張明文。
原理很簡單,作者根據所給口令(PASSPHRASE),使用和兩張圖片組成了一個圖片,這張圖片只與口令有關。然後對於加密內容,不需要替換的地方使用相反的圖片,需要替換的使用原本的圖片,這樣兩張圖片相疊就能達到需要的效果。
暫不討論此等加密的好壞,僅看到作者在最後那一串font的Array就讓我感歎。
閑來無事,也想自己寫個支援中文的,於是就有了C#版的VisualCrypto
由於其中使用了caozhy的字模點陣提取程式:
參見:http://topic.csdn.net/u/20120629/17/a33f88b5-7ee8-4a0c-8915-c0c721bb30c9.html
源碼也已上傳:http://files.cnblogs.com/nanqi/VisualCryptography.zip
個人思路:
首先將和使用私人欄位_unit代替
bool[][] _unit = new bool[][] { new bool[] { true, false, false, true }, new bool[] { false, true, true, false } };
將使用者輸入的口令處理為bool[256] dataCode即16*16的矩陣。
為true則使用第一個,為false使用第二個。最後得到bool[1024] _resultCode即32*32的矩陣。
通過字模點陣擷取bool[256] dataMsg即16*16的矩陣。
與口令擷取的bool[256] dataCode進行對比產生bool[256] dataDiff,dataMsg中為false的對dataCode取反,為true的不變。
與獲得resultCode方式相同,使用dataDiff獲得相應的_resultMsg。
畫出兩張圖。
具體代碼:
1 //密碼 2 byte[] code = System.Text.Encoding.Default.GetBytes(textBox1.Text.Trim()); 3 4 if (code.Length == 0) 5 { 6 code = DEF_CODE; 7 } 8 else if (code.Length > 16) 9 {10 code = code.Take(16).ToArray();11 }12 else13 {14 while (code.Length < 4)15 {16 code = code.Concat(code).ToArray();17 }18 }19 20 code = code.Concat(DEF_CODE.Skip(code.Length)).ToArray();21 22 IEnumerable<byte> tmpDataCode = Enumerable.Empty<byte>();23 24 for (int i = 0; i < code.Length; i += 4)25 {26 tmpDataCode = tmpDataCode.Concat(SHA512Encrypt(code.Where((by, index) => (index & 3) == (i / 4 & 3)).ToArray()));27 }28 29 bool[] dataCode = tmpDataCode.Select(by => Convert.ToBoolean(by & 1)).ToArray();
//字模Bitmap bmp = new Bitmap(16, 16);Graphics g = Graphics.FromImage(bmp);g.FillRectangle(Brushes.White, new Rectangle() { X = 0, Y = 0, Height = 16, Width = 16 });g.DrawString(textBox2.Text, textBox2.Font, Brushes.Black, Point.Empty);bool[] dataMsg = Enumerable.Range(0, 256).Select(a => new { x = a % 16, y = a / 16 }).Select(x => bmp.GetPixel(x.x, x.y).GetBrightness() > 0.5f ? false : true).ToArray();
1 //差異 2 bool[] dataDiff = dataCode.ToArray(); 3 4 if (dataMsg.Length == dataCode.Length) 5 { 6 for (int i = 0; i < dataMsg.Length; i++) 7 { 8 dataDiff[i] = dataMsg[i] ? dataDiff[i] : !dataDiff[i]; 9 }10 }11 12 //密匙13 IEnumerable<bool> tmpResultCode = Enumerable.Empty<bool>();14 15 foreach (var item in dataCode)16 {17 tmpResultCode = tmpResultCode.Concat(_unit[Convert.ToInt32(item)]);18 }19 20 _resultCode = tmpResultCode.ToArray();21 22 23 //訊息24 IEnumerable<bool> tmpResultMsg = Enumerable.Empty<bool>();25 26 foreach (var item in dataDiff)27 {28 tmpResultMsg = tmpResultMsg.Concat(_unit[Convert.ToInt32(item)]);29 }
void Draw(Graphics g, bool[] data){ for (int i = 0; i < 16; i++) for (int j = 0; j < 16; j++) for (int k = 0; k < 4; k++) { Brush brush = data[j * 4 * 16 + i * 4 + k] ? Brushes.Black : Brushes.White; if (k < 2) g.FillRectangle(brush, new Rectangle() { X = i * 16 + k * 8, Y = j * 16, Width = 8, Height = 8 }); else g.FillRectangle(brush, new Rectangle() { X = i * 16 + (k - 2) * 8, Y = j * 16 + 8, Width = 8, Height = 8 }); }}
源於:http://leemon.com/crypto/VisualCrypto.html
參見:http://topic.csdn.net/u/20120629/17/a33f88b5-7ee8-4a0c-8915-c0c721bb30c9.html
源碼:http://files.cnblogs.com/nanqi/VisualCryptography.zip