随机数字图片验证码的原理、生成和破解

验证码的功能一般是防止使用程序恶意注册、暴力破解或批量发帖而设置的。所谓验证码,就是将一串随机产生的数字或符号,生成一幅图片,图片里加上一些干扰象素(防止OCR),由用户肉眼识别其中的验证码信息,输入表单提交网站验证,验证成功后才能使用某项功能。学习验证码的破解/识别技术,不仅可以知道验证码的原理,而且可以让你知道怎样才能防止验证码被破解。

常见验证码类型

  1. 图片背景和数字都使用相同的颜色,字符规整,字符位置统一
  2. 验证字符规整,颜色相同,排除干扰素容易,只要是非字符色素全部排除即可
  3. 处理背景色和干扰色一直变换,验证字符的颜色也在变化,各个字符的颜色也各不相同
  4. 在第三个基础上,在文字上加了两条直线干扰率,容易去掉

验证码识别步骤

取出干扰素

干扰素的一个重要特征是不能影响验证码的显示效果,所以制作干扰素时它的RGB可能低于或高于某个特定值。比如例子中的图片,干扰素的RGB各项值小于125,依此很容易去掉干扰素。

取出字模

由于各个网站的验证码各不相同,最常见的方法是建立验证码的特征码库。取字模时,需要多收集几张图片,使这些图片中包括所有的字符。一般来说有0~9、a~z

二值化

把图片上的验证字符上每个像素用一种数字表示1,其他部分用0表示。这样就可以计算每个数字字模,记录下这些字模当作key

计算特征

把要识别的图片进行二值化,得到图片特征

对照样本

把上一步图片特征码和验证码的字模进行对比,得到验证图片上的数字

复杂验证码

识别的目标验证码由字符和数字组成,验证码存在旋转,位置不固定,存在字符与字符之间的粘连,且验证码有更强的干扰素。以下图为例:

二值化

把验证码的部分用1表示,背景部分用0表示。识别方法为:打印出验证码图片的RGB,分辨出图片的R值大于120,G和B小于80的像素,依据这个规则把图片二值化。

常见验证码第三张图片中,验证码的图片每次背景色都不相同,且不是单色,各个验证码数字的颜色每次也各不相同。打印出其 RGB 值很容易就发现。无论验证数字颜色如何变化,该数字的 RGB 值总有一个值小于 125 ,所以通过判断 rgbarray[‘red’] < 125 || rgbarray[‘green’] < 125 || rgbarray[‘blue’] < 125 就很容易分辨出数字和背景。

这些规律的原因是,在制作验证码的干扰素时,为了使干扰素不影响数字的显示效果,必须使干扰素的 RGB 和数字的 RGB 相互独立,互不干扰。依照这个规律就容易实现二值化。

我们找到的 120 , 80 , 125 等阈值,可能和实际的 RGB 有出入,所以,有时二值化后,会有部分地方出现 1 ,对于验证码上固定位置显示数字,这种干扰没有太大意义。但是对于验证码位置不确定的图片来说,在我们切割字符时,很可能造成干扰。所以,在二值化后要进行去噪处理。

去噪处理

去噪就是把孤立的有效值去掉。如果一个点为1,则判断这个点的周围一圈上的数字是否为1,若没有则认为是一个噪点,直接设置为0即可。

如图所示,红色方框部分的 1 为噪点,直接设置为 0 即可。有时候噪点可能是两个连续的 1 ,可以计算这个点 8 个方向上的值之和,判断和是否小于特定的阈值。

切割字符

切割方法有很多种,最简单的一种为竖直切割。先沿垂直方向切割为字符,然后再水平方向去掉多余的 0 。如下图所示

第一步切割红线部分,第二步切割蓝线部分,就可以得到独立的字符了。但是像下面的情况:

按上面的方法会把 dw 字符切割成一个字符,这是错误的切割,这里涉及到粘连字符的切割。

粘连字符切割

制作验证码时,规则字符的粘连很容易分割开,如果字符本身有缩放,变形就很难处理。上述字符粘连是规则字符的粘连,完成分割操作后,不能马上确定分割的部分为一个字符,要进行验证。验证的关键是切割下来的字符的宽是否大于阈值。阈值的取舍标准是一个字符无论怎么旋转变形都不会大于这个阈值。若切割的块大于这个阈值,可以认为是一个粘连字符;如果大于两个阈值之和,认为是三个字符粘连,以此类推。如果发现粘连字符块,直接平分为两个或多个小块即可。为了更好的还原字符,一般采用平分±1对字符块部分进行适当的补充。

匹配字符

最简单的方式是为所有的字符所有情况建立匹配库,目的是现有人工识别图片的验证码,处理后写入特征码库以便匹配。特征码库的图片数据越多,验证识别的准确性就越高。

制作验证码的建议

对于识别验证码的程序来说最难的部分是验证码字符的切割和特征码的建立。很多验证码加了很多干扰素和干扰线,不仅影响用户体验还达不到防止破解的很好的效果。若要使验证码难于被程序识别,需要注意:

  • 字符粘连,最后所有字符都有粘连的部分
  • 不使用规则字符,验证码的各个部分使用不同比例的缩放或者旋转

一般实现以上两点或这两点的变性,破解程序就很难识别。