Software Detection of Currency
The content on this web page was last updated in 2004, and is being maintained for archival purposes.
Recent printers, scanners and image manipulation software identify images of currency, will not process the image and display an error message linking to www.rulesforuse.org. The detection algorithm is not disclosed, however it is possible to test sample images as to whether they are identified as currency. This webpage shows an initial analysis of the algorithm’s properties, based on results from the automated generation and testing of images.
Currently only a few raw results are presented. You may also be interested in my IH04 talk on this subject given at the Information Hiding Workshop 2004 rump session. There are more details on the detection mechanism in my 21C3 talk at the 21st Chaos Communication Congress.
Initially it was thought that the “Eurion constellation” was used to identify banknotes in the newly deployed software based system, since this has been confirmed to be the technique used by colour photocopiers, and was both necessary and sufficient to prevent an item being duplicated using the photocopier tested. However further investigation showed that the detection performed by software is different from the system used in colour photocopiers, and the Eurion constellation is neither necessary nor sufficent, and in fact it probably is not even a factor.
This image, from the 10 Pound note contains all the Eurion
instances that are known of, but is not detected as currency:
However this image, which has one extra column of pixels at the right
is detected as currency:
Even if the constellations are blanked out:
Similar results can also be seen with the new US $20, in which the “0”s of the yellow “20”s scattered in the background form Eurion constellations.
Both PSP and Photoshop identify this image (from an Adobe Forum
discussion) as being currency and refuse to open it, despite there
being no instance of the Eurion constellation:
Another interesting property of this image is that it seems to be a
near minimal test case, since if any changes are made, then it is no
longer detected as currency. Even cropping away the black border will
result in it opening in PSP and Photoshop CS without any warning:
It is believed that some printers use histograms to detect currency.
If this is the feature used by PSP/Photoshop then removing the black
border could sufficiently change the histogram to circumvent the
detection system. However, this image, which is a tiled version of the
first image, is not detected as currency, despite having the same
The detection code of both PSP and Photoshop CS appears to be the same, due to them having the same edge cases. A static dissasembly reveals the string “DMRC” in symbols, the stock sticker code for Digimarc, a company specialising in watermarking. Subsequent news articles have confirmed that Digimarc developed the currency-detection code, on behalf of the Central Bank Counterfeit Deterrence Group (CBCDG), part of the G11 organisation). According to Adobe and Jasc, adding the detection code is “optional” and that they do not get access to the source code or details of the algorithm.
It seems that the algorithm is optimised to err on the side of false negatives, and I have not been able to generate a false positive. It has been reported that generating a false negative is easy, perhaps as simple as using images of two notes, side-by-side, rather than just one. A statement from Adobe said that the version included in Photoshop CS was not the first one proposed by the CBCDG, and previous revisions were rejected on the basis of having an unnaceptable false positive rate. Also, while dissasembly is difficult, it is likely to be comparatively easy to patch around the call to the detection code and bypass the detector.
Another observation is that unmodified banknotes images cause the error message to be displayed after a short time, also non-banknote images open quickly. However the edge cases made from modified banknote images take a few extra seconds before either opening or displaying the error message.
This would suggest that there is a series of tests, each of which provides a score on how much the image looks like a banknote, with the later ones which take longer to execute and presumably being more accurate. At each stage there could be is a upper and lower limit on the cumulative score, if the upper bound is reached the image is not opened and an error message displayed, if the lower bound is reached then the image is opened and no further tests are performed, otherwise the next test is executed.
Strongly Detected Regions
The image below shows the smallest square starting at each point on an English £20 note, which is still detected as currency. The starting points are generated at 500 pixel intervals and the size of each crop is calculated to a precision of 5 pixels. Starting points are marked by a green dot, end points by a red dot; the colour of the square is of no significance. Only the crops smaller than 700x700 have been drawn. The resulting image has been converted from PPM to PNG and scaled down from 3524x1906 to 800x433 for presentation.
The images below are full size versions of three smallest crops.
|Crop starting at (0, 0), size: 319x319||Crop starting at (0, 1500), size: 320x320||Crop starting at (3000, 1000), size: 362x362|
The tests below show the smallest distortion required to prevent a section of a banknote (an English £20) from being detected as currency. For each test, the image on the left is the original and the image on the right shows the least distorted image which is no longer detected as currency. The attacks themselves were performed by Checkmark. The caption shows the Checkmark function applied, along with the resulting value of the parameter which was varied. Each image is unscaled but has been converted from PPM to PNG for presentation.
|Original||After JPEG Compression: CM_jpegcompression(13.0)|
|Original||After Median Filtering: CM_medfilt(12.0)|
|Original||After Midpoint Filtering: CM_midpoint(10.0)|
Ratio Distortion (1 of 2)
|Original||After Ratio Distortion: CM_ratio(1.1)|
Ratio Distortion (2 of 2)
|Original||After Ratio Distortion: CM_ratio(0.9)|
|Original||After Rotation: CM_rotation(10.9)|
Rotation + Scaling
|Original||After Rotation + Scaling: CM_rotationscale(12.7)|
|Original||After Resampling: CM_sampledownup(0.8)|
Scaling (1 of 2)
|Original||After Scaling: CM_scale(0.8)|
Scaling (2 of 2)
|Original||After Scaling: CM_scale(2.0)|
|Original||After Shearing: CM_shearing(2.6)|
Trimmed Mean Filtering
|Original||After Trimmed Mean Filtering: CM_trimmedmean(12.0)|
|Original||After Warping: CM_warp(1.8)|
|Original||After Wavelet Compression: CM_waveletcompression(0.5)|
Wiener Noise Removal
|Original||After Wiener Noise Removal: CM_wiener(12.0)|