如何為數(shù)據(jù)庫中的位圖添加動態(tài)水印
譯文譯者 | 李睿
審校 | 重樓
概要
許多數(shù)據(jù)庫存儲了以blob或文件形式保存的位圖,其中包括照片、文檔掃描、醫(yī)學圖像等。當這些位圖被各種數(shù)據(jù)庫客戶端和應用程序檢索時,為了日后的識別和追蹤,有時需要在檢索時為它們添加唯一的水印。在某些情況下,人們甚至希望這些水印是不可見的。
這種動態(tài)的位圖操作可以很容易地通過可編程的數(shù)據(jù)庫代理完成,無需對持久化存儲的位圖進行任何修改。
這種方法有以下好處:
- 水印可以為每次檢索進行定制,并可以包含有關(guān)日期、時間、用戶身份、IP地址等信息。
- 圖像處理由代理完成,這樣不會給數(shù)據(jù)庫帶來額外的負載。
- 不需要更改數(shù)據(jù)庫或數(shù)據(jù)庫客戶端。
最終結(jié)果
給定一個存儲在數(shù)據(jù)庫中的位圖,例如下圖:
可編程的數(shù)據(jù)庫代理可以在發(fā)送到客戶端的途中修改位圖,以包含任何所需信息的水印,例如下圖:
工作原理
這個架構(gòu)很簡單:它并不依賴于傳統(tǒng)的數(shù)據(jù)庫客戶端與服務器之間的直接連接,而是采用了一種不同的方式:
客戶端連接到代理,代理連接到服務器:
然后,代理可以在檢索位圖時根據(jù)需要處理這些位圖。
例如,它只能為某些位圖添加水印,也可以根據(jù)具體情況使用不同樣式的水印。存儲在數(shù)據(jù)庫中的位圖完全不受影響:它們在轉(zhuǎn)發(fā)給客戶端時被動態(tài)修改。
優(yōu)點
- 客戶和數(shù)據(jù)庫對此一無所知——這對他們來說是完全透明的。
- 每當圖像被檢索時,都可以為其添加獨特的水印(例如,日期/時間、用戶名、客戶端的IP地址等)。
- 數(shù)據(jù)庫服務器上不會增加額外的負載。
缺點
- 由于添加了代理,系統(tǒng)變得更加復雜。
- 延遲會增加(通常是適度的),主要取決于圖像的大小,但應該與替代方案進行比較。
實例
使用代理,可以創(chuàng)建一個簡單的過濾器,為某些位圖添加水印。
如果假設數(shù)據(jù)庫包含一個名為images的表,其中包含一個名為bitmap的列,類型為blob或varbinary(取決于數(shù)據(jù)庫),可以在代理中使用以下參數(shù)創(chuàng)建一個結(jié)果集過濾器:
Query pattern: regex:select.*from.*images.*
以下一些JavaScript代碼(也使用底層Java引擎):
JavaScript
// Get the value of the bitmap column as a byte stream
let stream = context.packet.getJavaStream("bitmap");
if (stream === null) {
return;
}
// The text to use as watermark
const now = new Date();
const watermark = "Retrieved by " + context.connectionContext.userName +
" on " + now.getFullYear() + "/" + (now.getMonth()+1) + "/" + now.getDate();
// Read the bitmap
const ImageIO = Java.type("javax.imageio.ImageIO");
let img = ImageIO.read(stream);
// Create the Graphics to draw the text
let g = img.createGraphics();
const Color = Java.type("java.awt.Color");
g.setColor(new Color(255, 255, 0, 150));
const Font = Java.type("java.awt.Font");
g.setFont(new Font("sans-serif", Font.BOLD, 16));
// Draw the text at the bottom of the bitmap
let textRect = textFont.getStringBounds(watermark, g.getFontRenderContext());
g.drawString(watermark, (img.getWidth() / 2) - (textRect.getWidth() / 2),
img.getHeight() - (textRect.getHeight() / 2));
// Write the bitmap to the column value
const ByteArrayOutputStream = Java.type("java.io.ByteArrayOutputStream");
let outStream = new ByteArrayOutputStream();
ImageIO.write(img, "png", outStream);
context.packet.bitmap = outStream.toByteArray();
啟用這個過濾器之后,從這個表中檢索的位圖將包括一個水印,其中包含數(shù)據(jù)庫用戶的名稱和時間戳。
數(shù)據(jù)庫永遠不會受到影響:存儲在數(shù)據(jù)庫中的位圖完全不變,它們是在發(fā)送給客戶端時即時修改的。
顯然,可以選擇性地為位圖添加水印,可以根據(jù)任何相關(guān)因素更改水印的文本,還可以通過字體、顏色、定位、透明度等因素添加水印。有關(guān)詳細信息,參見這個示例。
秘密水印
在某些情況下,可能需要以肉眼不可見的方式標記位圖。一種簡單的方法是編輯圖像的元數(shù)據(jù),但如果需要更微妙的東西,可以使用隱寫術(shù)在位圖中分發(fā)秘密消息,使其難以被檢測到。
可以修改以上的示例以使用Adumbra庫:
// Get the value of the bitmap column as a byte stream
let inStream = context.packet.getJavaStream("bitmap");
if (inStream === null) {
return;
}
// The hidden message
const now = new Date();
const message = "Retrieved by " + context.connectionContext.userName +
" on " + now.getFullYear() + "/" + (now.getMonth()+1) + "/" + now.getDate();
const messageBytes = context.utils.getUTF8BytesForString(message);
const keyBytes = context.utils.getUTF8BytesForString("This is my secret key");
// Hide the message in the bitmap
const Encoder = Java.type("com.galliumdata.adumbra.Encoder");
const ByteArrayOutputStream = Java.type("java.io.ByteArrayOutputStream");
let outStream = new ByteArrayOutputStream();
let encoder = new Encoder(1);
encoder.encode(inStream, outStream, "png", messageBytes, keyBytes);
context.packet.bitmap = outStream.toByteArray();
有了這一點,提供給客戶端修改后的位圖將包含一個難以檢測的秘密水印,且在沒有密鑰的情況下幾乎無法提取。
水印技術(shù)還有哪些用途?
這種水印技術(shù)也可以應用于位圖以外的文檔:
- 像PDF和MS Word這樣的文檔可以被賦予一些額外的元數(shù)據(jù),或者它們可以被賦予一個可見或不可見的水印。可以參考PDF文檔的這個示例。
- 所有的文本文檔可以巧妙地使用水印技術(shù)進行標記,例如改變間距、拼寫、布局、字體和顏色、零寬度字符等。
- 所有能夠在不失去任何重要意義的情況下進行微小更改的數(shù)字文檔,例如位圖、音頻文件和樣本集,都能夠以類似的方式進行修改。
- 事實上,整個數(shù)據(jù)集可以通過巧妙地修改數(shù)據(jù)的一些非關(guān)鍵方面來添加水印,從而有可能在以后識別這些數(shù)據(jù)集并確切地知道它們的來源。這超出了本文的范圍,但是有許多方法可以使數(shù)據(jù)追溯到其起源。
結(jié)論
當需要從數(shù)據(jù)庫中檢索位圖或文檔時,并且每次檢索都需要一個定制的水印,這里展示的技術(shù)是一種可靠的方法,它避免了給數(shù)據(jù)庫帶來任何額外的負擔,并且不需要對客戶端或服務器進行任何更改。
原文標題:Dynamic Watermarking of Bitmaps in Databases,作者:Max Tardiveau