阿里巴巴內網的不可見水印用的是什麼演算法?
據說月餅事件截圖的那位員工也被開除了?
在阿里實習的時候,分析過這個東西,當然只是純好奇技術啦。對外公開內網的信息本身就是不道德的,而且可能觸犯保密協議。
首先,第一道防線。看截圖這個人是用阿里內外的iOS客戶端截的圖,且不說截下來的圖 PS 能不能完整去水印。在截圖操作的瞬間,客戶端首先就能感知到你有沒有截圖。 iOS 有這個 API,Android 也能通過監聽截圖保存路徑實現 ,做過移動端開發的人應該都有所了解。所以你在什麼時間、什麼頁面截了圖,其實都能記錄下來並上傳伺服器的。可參考:
RxScreenshotDetector:Android 截屏檢測
iOS開發-檢測用戶截屏, 並獲取所截圖片再者,第二道防線。在手機客戶端截圖是不方便去水印的。水印其實就是寫著工號的透明度很高的圖片,background-image 的方式平鋪滿整個屏幕。如果在 chrome里,直接審查元素去掉就行,這樣就去除乾淨了。如果先截了圖,再用 PS 去除的話,就有點麻煩了。因為用 PS 去除的話很容易漏掉一些東西,比如工號二進位。
(很多人不理解水印的原理,這裡多解釋幾句,這種高透明度的水印從正面看屏幕的話肉眼很難看到。從屏幕上下斜看,也能隱約看到一些。在 PS 里調下色階馬上就顯現出來了。 @Mize 已經做了個類似的效果,就是這樣 阿里巴巴內網的不可見水印用的是什麼演算法? - Mize 的回答 。)
第三道防線,很多人知道這個水印里有工號,但不知道還有工號的二進位。就是用.和/組成的二進位,和工號放在一張圖片里。工號的水印調調對比度、色階,甚至斜著看屏幕就能看到,但是「./」組成的二進位又小又隱蔽,所以用 PS 的話很容易漏掉。
最後一道防線,還記得之前阿里 HR 偽造員工離職談話的那個風波的時候。即便一個懂前端的程序員去除了水印,最後還是被查出來了,這是為什麼?個人推測,可能是根據截圖中的評論數、芝麻數等等隨著時間變化的數據,反推出截圖的時間區間,然後根據時間篩選訪問這個帖子的訪問日誌,縮小範圍到幾個人,再逐個約談,大概就能確定了。
很多知友說通過背景色差、文欄位落間距、排版什麼的就有點太高端了,阿里目前應該不會用到吧……
至於中間人監控員工上網信息,這個不了解還是別不推測了……下面的只是簡單的加一個很淺的水印,實現起來很容易。
用歐捏醬提供的代碼試了下:
瀏覽器終端下粘貼下面的代碼,它的作用是在當前頁面上增加了一個透明度只有0.005的很多hello的水印。
function watermark(settings) {
//默認設置
var defaultSettings={
watermark_txt:"text",
watermark_x:20,//水印起始位置x軸坐標
watermark_y:20,//水印起始位置Y軸坐標
watermark_rows:5,//水印行數
watermark_cols:5,//水印列數
watermark_x_space:10,//水印x軸間隔
watermark_y_space:90,//水印y軸間隔
watermark_color:"#000000",//水印字體顏色
watermark_alpha:0.005,//水印透明度
watermark_fontsize:"80px",//水印字體大小
watermark_font:"微軟雅黑",//水印字體
watermark_width:500,//水印寬度
watermark_height:90,//水印長度
watermark_angle:25//水印傾斜度數
};
//採用配置項替換默認值,作用類似jquery.extend
if(arguments.length===1typeof arguments[0] ==="object" )
{
var src=arguments[0]||{};
for(key in src)
{
if(src[key]defaultSettings[key]src[key]===defaultSettings[key])
continue;
else if(src[key])
defaultSettings[key]=src[key];
}
}
var oTemp = document.createDocumentFragment();
//獲取頁面最大寬度
var page_width = Math.max(document.body.scrollWidth,document.body.clientWidth);
//獲取頁面最大長度
var page_height = Math.max(document.body.scrollHeight,document.body.clientHeight);
//如果將水印列數設置為0,或水印列數設置過大,超過頁面最大寬度,則重新計算水印列數和水印x軸間隔
if (defaultSettings.watermark_cols == 0 || (parseInt(defaultSettings.watermark_x + defaultSettings.watermark_width *defaultSettings.watermark_cols + defaultSettings.watermark_x_space * (defaultSettings.watermark_cols - 1)) &> page_width)) {
defaultSettings.watermark_cols = parseInt((page_width-defaultSettings.watermark_x+defaultSettings.watermark_x_space) / (defaultSettings.watermark_width + defaultSettings.watermark_x_space));
defaultSettings.watermark_x_space = parseInt((page_width - defaultSettings.watermark_x - defaultSettings.watermark_width * defaultSettings.watermark_cols) / (defaultSettings.watermark_cols - 1));
}
//如果將水印行數設置為0,或水印行數設置過大,超過頁面最大長度,則重新計算水印行數和水印y軸間隔
if (defaultSettings.watermark_rows == 0 || (parseInt(defaultSettings.watermark_y + defaultSettings.watermark_height * defaultSettings.watermark_rows + defaultSettings.watermark_y_space * (defaultSettings.watermark_rows - 1)) &> page_height)) {
defaultSettings.watermark_rows = parseInt((defaultSettings.watermark_y_space + page_height - defaultSettings.watermark_y) / (defaultSettings.watermark_height + defaultSettings.watermark_y_space));
defaultSettings.watermark_y_space = parseInt(((page_height - defaultSettings.watermark_y) - defaultSettings.watermark_height * defaultSettings.watermark_rows) / (defaultSettings.watermark_rows - 1));
}
var x;
var y;
for (var i = 0; i &< defaultSettings.watermark_rows; i++) {
y = defaultSettings.watermark_y + (defaultSettings.watermark_y_space + defaultSettings.watermark_height) * i;
for (var j = 0; j &< defaultSettings.watermark_cols; j++) {
x = defaultSettings.watermark_x + (defaultSettings.watermark_width + defaultSettings.watermark_x_space) * j;
var mask_div = document.createElement("div");
mask_div.id = "mask_div" + i + j;
mask_div.appendChild(document.createTextNode(defaultSettings.watermark_txt));
//設置水印div傾斜顯示
mask_div.style.webkitTransform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
mask_div.style.MozTransform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
mask_div.style.msTransform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
mask_div.style.OTransform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
mask_div.style.transform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
mask_div.style.visibility = "";
mask_div.style.position = "absolute";
//選不中
mask_div.style.left = x + "px";
mask_div.style.top = y + "px";
mask_div.style.overflow = "hidden";
mask_div.style.zIndex = "9999";
mask_div.style.pointerEvents = "none";
//mask_div.style.border="solid #eee 1px";
mask_div.style.opacity = defaultSettings.watermark_alpha;
mask_div.style.fontSize = defaultSettings.watermark_fontsize;
mask_div.style.color = defaultSettings.watermark_color;
mask_div.style.textAlign = "center";
mask_div.style.width = defaultSettings.watermark_width + "px";
mask_div.style.height = defaultSettings.watermark_height + "px";
mask_div.style.display = "block";
oTemp.appendChild(mask_div);
};
};
document.body.appendChild(oTemp);
}
watermark({ watermark_txt:"hello"})
用qq截了個圖,一點都看出不來。
現在把圖片放到PS裡面,建一個圖層在上面。全部填充為黑色,混合模式選擇正片疊底這一類的(也就是讓亮的更亮,暗的更暗),一個個試。
當我試到hard mix的時候,水印就顯示出來了。城裡套路太深。解決方法的思路
- 另存為jpg,壓縮,還是能搞出來,這一點對比並沒有丟失掉。
- 裝個保護視力的濾鏡之類東西?懶得試了。- 減少色深,這種小的對比就看不見了。==========================================
另外在一個類似的問題的答案里提到一種方法,在圖片頻域里添加水印,涉及到信號處理的專業知識。這種方法更隱秘,也更專業更難去除,可以去看看。實現頻域水印,猜想實現起來比較困難,得挾持手機自帶的截圖功能才行。&>&>&> 阿里巴巴公司根據截圖查到泄露信息的具體員工的技術是什麼? - fuqiang liu 的回答你們別瞎猜了,哪有這麼複雜......
就是伺服器吐了個帶工號的水印,一句 CSS 鋪在後面,幹掉 background 就好了…怎奈這個哥們太不小心,用的 PS,唉。
---- update ----
評論指出
- 還原出來的圖片非常清晰,所有的工號位置的工號都是完整清晰的
- 那層水印除了可見的工號外,其不可見的部分可能才是玄機所在……個人認為在顏色中做很難,因為大部分截圖工具都會對圖片重新編碼。但如果確實存在這樣的黑科技,那麼本答案沒有幫助,希望有內行高人來聊一聊編碼和演算法學過點皮毛的來強答一發,不太清楚阿里具體用了什麼演算法,因此在這裡僅介紹一下數字水印。
數字水印本身是應用非常廣泛的一個技術。對它的研究也日漸深入。數字水印的核心是信息隱藏技術,而信息隱藏是在承載媒介中隱藏某些信息的技術。從這點上來說,信息隱藏的承載媒介不僅僅可以是圖片,也可以是文字,也可以是標點符號。不過現在研究比較多的還是圖片和音頻視頻的信息隱藏。
信息隱藏研究的目標總結起來有:1、提高容量,在更少的承載媒介中隱藏儘可能多的信息;2、低可探測性,隱藏信息之後的承載媒介在統計上應該儘可能接近未隱藏信息承載媒介;3、高安全性,一方面被隱藏的信息無法被沒有密鑰的敵手獲取,另一方面被隱藏的信息不會由於壓縮(如圖像、音頻視頻的各種壓縮演算法,圖像模糊演算法,手動扣圖之類等)而被破壞。
現有的圖像信息隱藏技術已經可以很好的騙過人眼並且在被多次反覆壓縮的狀況下仍然可以正確的提取隱藏數據;而像F5和更新的基於HVS的信息隱藏演算法甚至使用計算機程序都無法找到存在的痕迹。因此如果阿里技術夠強,遠不是在背景中加幾個像素點這麼簡單,也絕不是把EXIF刪掉或者用JPG壓縮幾遍就能解決的。
-----------------PS:公司在其內部系統里加數字水印用來做機密失竊溯源是很正常的做法。各位噴HR可以,噴內部系統設計完全沒有必要。PSS:非常期待公安內部的查詢系統搞上數字水印,打擊那些一言不合就公開別人隱私的不良行為。
我就問一下,這個技術是否可以抗差分分析?找不同人的同一內容,分析不同人的展示的差異。看看能不能逆向出演算法。如果可以做到單向函數一次一密的效果,那就牛逼了。
可以用一些非常淡的點構成的文字或者圖像來表示,比如簡單來說,一張圖片由紅藍綠三個顏色組合而成,每個像素每個顏色可以有0-255個顏色深度,可以在其中紅色部分的特定或者隨機位置加上1個顏色深度的圖像或者文字表示瀏覽者的身份,這個用肉眼是無法識別的,用工具就很容易做到。
肯定不是頻域嘛,這張圖是系統截圖啊,不是他生成的圖,工程上不可行。但是想法還是很好的。
應該就是加了一層很淡的水印,肉眼很難觀察到(理論上也能觀察到),但是一旦想追究,調大對比度就能看出來了
很久以前我就在PPT上用這個方法加上只有我電腦屏幕上才能看到的字,投影儀的對比度比液晶屏差遠了,所以看不到我只想說,界面的記者寫稿子全憑腦補,給他們報料的估計也就是我廠兩個圍觀看熱鬧的外圍員工。我就是那個截圖的人,圖是我截的,但水印不是我去掉的,也不是我往外發的。之所以不去水印,一是因爲我不會,二是因爲我壓根沒想往外發。
比如白色底色,顏色代碼FFFFFF,替換一個點FFFFFE,肉眼基本不可見,替換點的方式有css背景色或者背景圖片。再根據點的特定位置,換算到工號。技術上還是可以識別或者屏蔽,下次截圖的小心點就是。懂的搞不好還可以ps一下點的位置,陷害他人,細思極恐。
http://web.jobbole.com/87900/ 是不是類似這種 把工號id編碼到前端頁面的色值里
出事了拿流出截圖來找像素點見不得人的事情做多了,內網信息太齷齪了。才需要用這種手段
哇,工號都排到這兒了,當年俺的工號才4萬多
只想說,看來以後要八卦什麼的,低解析度小可視角屏幕拍照才是王道。。
一些淺見,歡迎批評指正。圖片的信息隱藏技術上有幾種辦法:一是在圖片頭文件裡面修改信息;二是在圖片文件的冗餘空間增加自定義的信息;三是在圖片信息里用空域、變換域和幾何域的數字水印方法嵌入信息,至於嵌入的水印信息可能是員工ID。
不過我感覺這個被查出更有可能是扒取伺服器網關數據造成的?
這個很容易實現哈。
將圖像分塊,做離散餘弦變換,即DCT,然後每塊的DCT係數會根據水印圖像像素信息進行增加或減少。變化後的DCT係數,再做離散反餘弦變換即可。
在想可能接下來就不太管用了?這梗被用了,之後就能拿來栽贓嫁禍 ...
如果用深度學習的style tranfer對圖片做處理 能消除嗎
很多視頻晶元就支持數字水印,華為海思就生產這樣的晶元。。。畢竟硬體打水印比軟體靠譜的多。。。還省事。。
華為自稱也有自己的反截屏反拍照手段,是不是用了相似的技術?
我們這得安卓客戶端內部app直接無法截圖,ios可以截圖,並且姓名工號水印貼滿屏,ps都難。
推薦閱讀: