《数据完整性和所有者的确认》由会员分享,可在线阅读,更多相关《数据完整性和所有者的确认(24页珍藏版)》请在金锄头文库上搜索。
1、第四章 数据完整性和所有者的确认,消息摘要和签名,第二章用加密的方法实现了信息内容的保密性要求,但安全性编程还要求具有不可篡改性的要求,身份确定性的要求和不可否认性的要求。 通过消息摘要,消息验证码和数字签名数字证书等技术可以实现这些功能。,主要内容,通过消息摘要验证数据是否被篡改 通过消息验证码验证数据是否被篡改 通过数字签名验证数据的身份 使用消息摘要保存和验证口令 字典式攻击和加盐技术,计算消息摘要,消息摘要是对原始数据按照一定算法进行计算得到的结果,它主要用于检验原始数据是否被被修改过。 编程思路: (1)生成MessageDigest对象 (2)传入需要计算的字符串 (3)计算消息摘
2、要 (4)处理计算结果 例:java DigestCalc abc,基于输入流的消息摘要,实际使用中经常要对流计算消息摘要,这时虽然可以从流中读出所有字节然后计算,但是使用DigestInputStream类更加方便。 编程思路: (1)生成MessageDigest对象,指定消息摘要算法。 (2)生成需要计算的输入流 (3)生成DigestInputStream对象 (4)从DigestInputStream流中读取数据 (5)计算消息摘要 例:java DigestInput DigestInput.java,输入流中指定内容的消息摘要,有时我们不是需要计算文件中所有内容的消息摘要,只是需
3、要文件中指定内容的消息摘要。 例:计算文件输入流中第一次出现“$”以后内容的消息摘要。Java DigestInputLine 1.txt 编程思路: (1)生成MessageDigest和DigestInputStream对象 (2)先关闭消息摘要功能 (3)从DigestInputStream流中读出数据 (4)若读到的消息为“$”,则开启消息摘要功能 (5)计算消息摘要,基于输出流的消息摘要,例:从键盘读入数据,然后使用DigestOutputStream对象将数据写入文件输出流,同时计算其消息摘要。 编程思路: (1)生成MessageDigest对象 (2)生成需要的输入流 (3)生
4、成DigestOutputStream对象 (4)向DigestOutputStream流中写数据 (5)关闭DigestOutputStream流 (6)计算消息摘要 例:java DigestOutput tmp.txt 输入数据用ctrl+z结束,使用消息验证码,当A将数据传输给B时,可以同时将对应的消息摘要传递给B.B收到后可以用消息摘要验证数据在传输过程中是否被篡改过。但这样做的前提是A传递给B的消息摘要正确无误。如果攻击者在修改原始数据的同时重新计算一下消息摘要,然后将A传递给B的消息摘要替换掉,则B通过消息摘要就无法验证出原始数据是否被修改过。 消息验证码可以解决这个问题,使用消
5、息验证码的前提是A和B有一个共同的密钥,这样A可以将消息摘要加密发送给B,防止消息摘要被篡改。由于使用了共同的密钥,接受者可以在一定程度上验证发送者的身份:一定是和自己拥有共同密钥的人,所以称为“验证码”。,数据篡改攻击,攻击者在非法读取数据后,进行篡改数据,以达到通信用户无法获得真实信息的攻击目的。,篡改攻击,使用散列函数篡改消息m,和散列后的值H(m),编程思路: (1)生成密钥对象 (2)生成MAC对象 (3)传入需要计算的字符串 (4)计算消息验证码 (5)处理计算结果 例:java MyMac “How are you”,使用数字签名确定数据的来源,使用消息摘要和消息验证码保证了数据
6、未经过修改,但接收者无法确定数据是否确实是某人发来的,但这要求双方具有共享的密钥,当数据要提供给一组用户、这一组用户都需要确定数据的来源时,消息验证码就不方便了。 数字签名可以解决这个问题,消息验证码的基础是基于公钥和私钥的非对称加密,发送者用私钥加密,接收者用公钥验证,用户1,用户2,用户3,用户4,用户5,在对称密码下,用户1与其他每一个用户之间都需要一对共享密钥,加大了密钥管理的难度,编程思路: (1)获取要签名的数据 (2)获取私钥 (3)获取Signature对象 (4)用私钥初始化Signature对象 (5)传入要签名的数据 (6)执行签名(包括散列和私钥加密) 例:java S
7、ign,使用公钥验证数字签名,当接收者收到签名后,可以用公钥进行验证。 编程思路: (1)获取要签名的数据 (2)获取签名 (3)读取公钥 (4)获取Signature对象 (5)用公钥初始化Signature对象 (6)传入要签名的数据 (7)检验签名 例:java CheckSign,假如文件msg.dat及其数字签名Sign.dat在传递过程中被做了手脚,我们可以对两个文件做任意的修改来模拟,将得到错误的检验结果。 数字签名也可以实现不可否认性,若接受者拥有了msg.dat和响应的签名文件Sign.dat,以后发送者不承认msg.dat中的内容,则接受者可以让仲裁者使用A对外公开的公钥文
8、件Skey_RSA_pub.dat来检验msg.dat和Sign.dat。反过来,若A怀疑接受者出示的msg.dat是否做过手脚,也可以请仲裁者来检验Sign.dat文件。,使用消息摘要保存口令,程序中经常需要验证用户输入的口令是否正确,如果将正确的用户口令直接存放在程序,文件或数据库中,则很容易被黑客窃取到,这时,可以只保存口令的消息摘要。 每次用户输入口令,然后将口令变换成消息摘要再和保存在文件中的消息摘要对比是否相同,若相同则是正确的口令。,实例:运行 java SetPass 帐号 口令,将把帐号以明文方式保存在文件passwd.txt中,而把口令的消息摘要保存在passwd.txt
9、编程思路: (1)读入帐号口令 (2)生成MessageDigest对象 (3)传入需要计算的字节数组 (4)计算消息摘要 (5)在文件或数据库中保存帐号和口令的消息摘要,使用消息摘要验证口令,实例:运行“java CheckPass 帐号 口令”,若帐号和口令都和保存在passwd.txt中的相同,则提示“OK”,否则提示“Wrong password”. 编程思路: (1)根据用户输入的帐号读取文件中对应的口令的消息摘要。 (2)计算用户输入的口令的消息摘要 (3)比较用户输入的口令的消息摘要和文件中保存的口令摘要是否一致,攻击消息摘要保存的口令,由于使用了散列函数,即使知道了口令摘要也难
10、以推出口令的值,但是当口令比较短时,攻击者很容易通过字典式攻击由口令的消息摘要反推出原有口令的值。 编程思路:事先计算好各种长度的字符组合所得到的字符串的消息摘要,将其保存在文件(字典)中,这虽然要花很多时间,但只需要做一次,以后如果攻击者得到某个人的口令消息摘要,则不需要进行耗时的计算,直接和字典中的值相匹配,即可知道用户的口令,如把所有四个字母的组合的摘要列出来。 例:制作字典java AttackPass,如果攻击者做好了字典,也知道了消息摘要的值,就可以使用查找的方法来获得摘要对应的口令值。 例:java DoAttack ac52ec0378cab76c5265a28e2a3cd0f
11、1,使用加盐技术防范字典式攻击,上节口令被轻松攻击的主要原因在于口令过短,如果口令很长,则计算所有组合的消息摘要可能要成百上千年,这将大大加大生成字典的难度。 不过口令很长也给用户带来不便,用户不方便记忆,因此用户使用的口令长度是有限的.加盐技术可在有限的口令长度基础上增加攻击者生成字典的难度。 加盐技术的原理是:在用户输入的口令前面加上一串随机数(称为盐),然后将随机数和口令组合在一起计算消息摘要,最后将随机数和消息摘要一起保存。 例:java SetPassSalt abc 123456,验证加盐的口令,编程思路: (1)根据用户输入的帐号读取对应的盐和消息摘要。 (2)将盐值转换为byt
12、e数组 (3)计算用户输入的口令的消息摘要 (4)比较用户输入的口令的消息摘要和文件中保存的口令摘要是否一致。 例:java CheckPassSalt abc 123456,对加盐口令的攻击,如果攻击者想要得到有盐的消息摘要,可以将盐和口令看成一个整体,如果盐是12字节,口令是4字节,那么攻击者需要生成长度分别为116个字节的所有字母可能组合,才能一劳永逸地通过简单的匹配来获得消息摘要对应的口令,但盐和口令的长度足够时,这种计算被认为是不可能完成的。,小结,数字签名验证实际上是公钥对应的私钥持有者认可了某个数据,但这个私钥持有者不一定可靠。攻击者可能自己生成一个私钥和公钥,对外宣称该公钥是A的。这样,接收者被误导。因此,验证数字签名所使用的公钥必须是从可靠的途径得到的,如通过信誉很好的报纸或网站等,此外,下一章的数字证书也将从计算机的角度解决这一问题。,