范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

关于加解密加签验签的那些事得物技术

  1前言
  面对MD5、SHA、DES、AES、RSA等等这些名词你是否有很多问号?这些名词都是什么?还有什么公钥加密、私钥解密、私钥加签、公钥验签。这些都什么鬼?或许在你日常工作没有听说过这些名词,但是一旦你要设计一个对外访问的接口,或者安全性要求高的系统,那么必然会接触到这些名词。所以加解密、加签验签对于一个合格的程序员来说是必须要掌握的一个概念。接下来我们就一文彻底搞懂这些概念。 2没有硝烟的战场——浅谈密码技术
  没有根基也许可以建一座小屋,但绝对不能造一座坚固的大厦。
  密码这个词有很多种的解释,在现代社会如果不接触编程的话,那么普遍的认为是我们设置的登录密码、或者是去银行取钱时输入的数字。都是我们在注册时实现给提供服务的一方存储一组数字,以后我们登录的时候就用这组数字相当于就证明了我们的身份。这个数字通常来说就是叫做密码。
  而我们需要了解的不是上面说的密码,而是一种"密码术",就是对于要传递的信息按照某种规则进行转换,从而隐藏信息的内容。这种方法可以使机密信息得以在公开的渠道传递而不泄密。使用这种方法,要经过加密过程。在加密过程中我们需要知道下面的这些概念:
  原文:或者叫明文,就是被隐藏的文字
  加密法:指隐藏原文的法则
  密文:或者叫伪文,指对原文按照加密法处理过后生成的可公开传递的文字
  密钥:在加密法中起决定性的因素,可能是数字、词汇,也可能是一些字母,或者这些东西的组合
  加密的结果生成了密文,要想让接受者能够读懂这些密文,那么就要把加密法以及密钥告诉接受者,否者接受者无法对密文解密,也就无法读懂原文。
  从历史的角度来看,密码学大概可以分为古典密码学和近现代密码学两个阶段。两者以现代信息技术的诞生为分界点,现在所讨论的密码学多指的是后者,建立在信息论和数学成果基础之上的。 2.1 古典密码学
  古典密码学源自于数千年前,最早在公元前1900年左右的古埃及,就出现了通过使用特殊字符和简单替换式密码来保护信息。美索不达米亚平原上曾经出土一个公元前1500年左右的泥板,其上记录了加密描述的陶瓷器上釉的工艺配方。古希腊时期(公元前800 ﹣前146 年)还发明了通过物理手段来隐藏信息的"隐写术",例如使用牛奶书写、用蜡覆盖文字等。后来在古罗马时期还出现了基于替换加密的凯撒密码,据称凯撒曾用此方法与其部下通信而得以命名。这些手段多数是采用简单的机械工具来保护秘密,在今天看来毫无疑问是十分简陋,很容易猜出来的。严格来看,可能都很难称为密码科学。
  凯撒密码是当偏移量是3的时候,所有的字母都A都将被替换成D,B变成E,以此类推。
  2.2 近代密码学
  近代密码学的研究来自于第一、二次世界大战中对于军事通信进行保护和猜出来的需求。1901年12月,意大利的工程师Guglielmo Marconi(奎里亚摩•马可尼)成功完成了跨越大西洋的无线电通信的实验,在全球范围内引发轰动,推动了无线电通信时代的到来。无线电大大提高了远程通信的能力,但是它有一个天然的缺陷——很难限制接收方,这就意味着你所传的信息有可能被拦截,因此就催生了加密技术的发展。
  对于无线电信息进行加密和解密也直接促进了近现代密码学和计算机技术的出现。反过来这些科技进步也影响了时代的发展。一战时期德国外交部长Arthur Zimmermann(阿瑟•齐默尔曼)拉拢墨西哥构成抗美军事同盟的电报(1917 年1月16日)被英国情报机构—40号办公室破译,直接导致了美国的参战;二战时期德国使用的恩尼格玛(Enigma)密码机(当时最先进的加密设备)被盟军成功破译(1939年到1941年),导致大西洋战役德国失败。据称,二战时期光英国从事密码学研究的人员就达到7000人,而他们的成果使二战结束的时间至少提前了一到两年时间。
  接下来就是可以称之为是密码学发展史上里程碑的事件了。1945年9月1日,Claude Elwood Shannon(克劳德•艾尔伍德•香农)完成了划时代的内部报告《A Mathematical Theory of Cryptography(密码术的一个数学理论)》,1949 年 10 月,该报告以《Communication Theory of Secrecy Systems(保密系统的通信理论)》为题在 Bell System Technical Journal(贝尔系统技术期刊)上正式发表。这篇论文首次将密码学和信息论联系到一起,为 对称密码技术  提供了数学基础。这也标志着近现代密码学的正式建立。这也是密码学发展史上的第一座里程碑性事件。
  密码学发展史上的第二个里程碑性事件是DES的出现。DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的分组密码算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。
  密码学发展史上的第三个里程碑性事件就是我们区块链中广泛应用的公钥密码,也就是 非对称密码算法  的出现。1976年11月,Whitfield Diffie 和 Martin E.Hellman 在 IEEE Transactions on Information Theory 上发表了论文《New Directions in Cryptography(密码学的新方向)》,探讨了无需传输密钥的保密通信和签名认证体系问题,正式开创了现代公钥密码学体系的研究。在公钥密码发现以前,如果需要保密通信,通信双方事先要对加解密的算法以及要使用的密钥进行事先协商,包括送鸡毛信,实际上是在传送密钥。但自从有了公钥密码,需要进行秘密通信的双方不再需要进行事前的密钥协商了。公钥密码在理论上是不保密的,在实际上是保密的。也就是说,公钥密码是可以猜出来的,但需要极长的时间,等到猜出来了,这个秘密也没有保密的必要了。
  上面我们说到了关于近现代的密码学相关的东西,基本上总结下来我们现在常用的就两个,一个是对称加密算法,一个是非对称加密算法。那么接下来我们就以介绍这两个概念为主线引出开题中我们提到的概念。 3程序实现3.1 对称加密算法
  对称加密指的就是加密和解密使用同一个秘钥,所以叫做对称加密。对称加密只有一个秘钥,作为私钥。具体的算法有:DES、3DES、TDEA、Blowfish,RC5,IDEA。但是我们常见的有:DES、AES等等。
  那么对称加密的优点是什么呢?算法公开、计算量小、加密速度快、加密效率高。缺点就是秘钥的管理和分发是非常困难的,不够安全。在数据传送前,发送方和接收方必须商定好秘钥,然后双方都必须要保存好秘钥,如果一方的秘钥被泄露了,那么加密的信息也就不安全了。另外,每对用户每次使用对称加密算法时,都需要使用其他人不知道的唯一秘钥,这会使得收、发双方所拥有的的钥匙数量巨大,秘钥管理也会成为双方的负担。
  加密的过程我们可以理解为如下: 加密:原文+秘钥 = 密文 解密:密文-秘钥 = 原文
  可以看到两次过程使用的都是一个秘钥。用图简单表示如下:
  3.2实战演练
  既然我们知道关于对称加密算法的相关知识,那么我们日常用Java如何实现对称加密的加密和解密动作呢?常见的对称加密算法有:DES、AES等。 3.2.1 DES
  DES加密算法是一种分组密码,以64位为分组对数据加密,它的密钥长度是56位,加密解密用同一算法。DES加密算法是对密钥进行保密,而公开算法,包括加密和解密算法。这样,只有掌握了和发送方相同密钥的人才能解读由DES加密算法加密的密文数据。因此,破译DES加密算法实际上就是搜索密钥的编码。对于56位长度的密钥来说,如果用穷举法来进行搜索的话,其运算次数为2的56次方。
  接下来用Java实现DES加密 public static void main(String[] args) throws Exception {         String data = "123 456";         String key = "wang!@##34;;         System.err.println(encrypt(data, key));         System.err.println(decrypt(encrypt(data, key), key));      }  /**      * Description 根据键值进行加密      * @param data      * @param key  加密键byte数组      * @return      * @throws Exception      */ public static String encrypt(String data, String key) throws Exception { byte[] bt = encrypt(data.getBytes(), key.getBytes());         String strs = new BASE64Encoder().encode(bt); return strs;     }  /**      * Description 根据键值进行解密      * @param data      * @param key  加密键byte数组      * @return      * @throws IOException      * @throws Exception      */ public static String decrypt(String data, String key) throws IOException,             Exception { if (data == null) return null;         BASE64Decoder decoder = new BASE64Decoder(); byte[] buf = decoder.decodeBuffer(data); byte[] bt = decrypt(buf,key.getBytes()); return new String(bt);     }  /**      * Description 根据键值进行加密      * @param data      * @param key  加密键byte数组      * @return      * @throws Exception      */ private static byte[] encrypt(byte[] data, byte[] key) throws Exception { // 生成一个可信任的随机数源         SecureRandom sr = new SecureRandom();  // 从原始密钥数据创建DESKeySpec对象         DESKeySpec dks = new DESKeySpec(key);  // 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);         SecretKey securekey = keyFactory.generateSecret(dks);  // Cipher对象实际完成加密操作         Cipher cipher = Cipher.getInstance(DES);  // 用密钥初始化Cipher对象         cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);  return cipher.doFinal(data);     }   /**      * Description 根据键值进行解密      * @param data      * @param key  加密键byte数组      * @return      * @throws Exception      */ private static byte[] decrypt(byte[] data, byte[] key) throws Exception { // 生成一个可信任的随机数源         SecureRandom sr = new SecureRandom();  // 从原始密钥数据创建DESKeySpec对象         DESKeySpec dks = new DESKeySpec(key);  // 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);         SecretKey securekey = keyFactory.generateSecret(dks);  // Cipher对象实际完成解密操作         Cipher cipher = Cipher.getInstance(DES);  // 用密钥初始化Cipher对象         cipher.init(Cipher.DECRYPT_MODE, securekey, sr);  return cipher.doFinal(data);     }
  输出以后可以看到数据被加密了 5fiw/XhRJ0E= 123 456
  在Java中用DES加密有一个特殊的地方
  (1)秘钥设置的长度必须大于等于8
  (2)秘钥设置的长度如果大于8的话,那么只会取前8个字节作为秘钥
  为什么呢,我们可以看到在初始化DESKeySpec类的时候有下面一段,其中var1是我们传的秘钥。可以看到他进行了截取。只截取前八个字节。 public DESKeySpec(byte[] var1, int var2) throws InvalidKeyException {     if (var1.length - var2 < 8) {         throw new InvalidKeyException("Wrong key size");     } else {         this.key = new byte[8];         System.arraycopy(var1, var2, this.key, 0, 8);     } } 3.2.2 AES
  AES加密算法是密码学中的高级加密标准,该加密算法采用对称分组密码体制,密钥长度的最少支持为128、192、256,分组长度128位,算法应易于各种硬件和软件实现。这种加密算法是美国联邦政府采用的区块加密标准,AES标准用来替代原先的DES,已经被多方分析且广为全世界所使用。
  JCE,Java Cryptography Extension,在早期JDK版本中,由于受美国的密码出口条例约束,Java中涉及加解密功能的API被限制出口,所以Java中安全组件被分成了两部分: 不含加密功能的JCA(Java Cryptography Architecture )和含加密功能的JCE(Java Cryptography Extension)。
  JCE的API都在javax.crypto包下,核心功能包括:加解密、密钥生成(对称)、MAC生成、密钥协商。
  加解密功能由Cipher组件提供,其也是JCE中最核心的组件。
  在设置Cipher 类的时候有几个注意点:
  (1)Cipher在使用时需以参数方式指定transformation
  (2)transformation的格式为algorithm/mode/padding,其中algorithm为必输项,如: AES/DES/CBC/PKCS5Padding,具体有哪些可看下表
  (3)缺省的mode为ECB,缺省的padding为PKCS5Padding
  (4)在block算法与流加密模式组合时, 需在mode后面指定每次处理的bit数, 如DES/CFB8/NoPadding, 如未指定则使用缺省值, SunJCE缺省值为64bits
  (5)Cipher有4种操作模式: ENCRYPT_MODE(加密), DECRYPT_MODE(解密), WRAP_MODE(导出Key), UNWRAP_MODE(导入Key),初始化时需指定某种操作模式
  秘钥的可以由我们自己定义,也可以是由AES自己生成,当自己定义是需要是要注意:
  (1)根据 AES 规范,可以是 16 字节、24 字节和32 字节长,分别对应 128 位、192 位和 256 位;
  (2)为便于传输,一般对加密后的数据进行 base64 编码: /*          * 此处使用AES-128-ECB加密模式,key需要为16位。          */         String cKey = "1234567890123456"; // 需要加密的字串         String cSrc = "buxuewushu";         System.out.println(cSrc); // 加密         String enString = Encrypt(cSrc, cKey);         System.out.println("加密后的字串是:" + enString);  // 解密         String DeString = Decrypt(enString, cKey);         System.out.println("解密后的字串是:" + DeString);     }  // 加密 public static String Encrypt(String sSrc, String sKey) throws Exception { if (sKey == null) {             System.out.print("Key为空null"); return null;         } // 判断Key是否为16位 if (sKey.length() != 16) {             System.out.print("Key长度不是16位"); return null;         } byte[] raw = sKey.getBytes("utf-8");         SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");         Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"         cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));  return new Base64().encodeToString(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。     }  // 解密 public static String Decrypt(String sSrc, String sKey) throws Exception { try { // 判断Key是否正确 if (sKey == null) {                 System.out.print("Key为空null"); return null;             } // 判断Key是否为16位 if (sKey.length() != 16) {                 System.out.print("Key长度不是16位"); return null;             } byte[] raw = sKey.getBytes("utf-8");             SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");             Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");             cipher.init(Cipher.DECRYPT_MODE, skeySpec); byte[] encrypted1 = new Base64().decode(sSrc);//先用base64解密 try { byte[] original = cipher.doFinal(encrypted1);                 String originalString = new String(original,"utf-8"); return originalString;             } catch (Exception e) {                 System.out.println(e.toString()); return null;             }         } catch (Exception ex) {             System.out.println(ex.toString()); return null;         }     } 3.3 非对称加密算法
  非对称加密算法中加密和解密用的不是同一个秘钥,所以叫作非对称加密算法。在非对称加密算法每个用户都有两把钥匙,一把公钥一把私钥。公钥是对外发布的,所有人都看的到所有人的公钥,私钥是自己保存,每个人都只知道自己的私钥而不知道别人的。而也正是在非对称加密算法中有加密和解密、加签和验签的概念。接下来我们解释一下这几个概念是什么意思。 3.3.1 加密和解密
  用该用户的公钥加密后只能该用户的私钥才能解密。这种情况下,公钥是用来加密信息的,确保只有特定的人(用谁的公钥就是谁)才能解密该信息。所以这种我们称之为加密和解密。
  下面我拿A银行和小明来举例子吧。假设这2者之间是用不对称的加密算法来保证信息传输的安全性(不被第三人知道信息的含义及篡改信息)。大致流程如下:首先小明发了一条信息给A银行"我要存500元"。这条信息小明会根据A银行的对外发布的公钥把这条信息加密了,加密之后,变成"XXXXXXX"发给A银行。中间被第三者截获,由于没有A银行的私钥无法解密,不能知道信息的含义,也无法按正确的方式篡改。所以拿这条加密信息是没办法的。最后被A银行接受,A银行用自己的私钥去解密这条信息,解密成功,读取内容,执行操作。然后得知消息是小明发来的,便去拿小明的公钥,把"操作成功(或失败)"这条信息用小明的公钥加密,发给小明。同理最后小明用自己的私钥解开,得知知乎发来的信息内容。其他人截获因为没有小明的私钥所以也没有用。 3.3.2 加签和验签
  还有第二种情况,公钥是用来解密信息的,确保让别人知道这条信息是真的由我发布的,是完整正确的。接收者由此可知这条信息确实来自于拥有私钥的某人,这被称作数字签名,公钥的形式就是数字证书。所以这种我们称之为加签和验签。
  继续拿小明和银行A举例子。银行A发布了一个银行客户端的补丁供所有用户更新,那为了确保人家下载的是正确完整的客户端,银行A会为这个程序打上一个数字签名(就是用银行A的私钥对这个程序加密然后发布),你需要在你的电脑里装上银行A的数字证书(就是银行对外发布的公钥),然后下载好这个程序,数字证书会去解密这个程序的数字签名,解密成功,补丁得以使用。同时你能知道这个补丁确实是来自这个银行A,是由他发布的,而不是其他人发布的。 3.3.3 实战演练
  我们在开发过程中经常使用的非对称加密算法之一就是RSA算法。接下来我们使用Java实现RSA算法。
  生成密钥
  首先是生成key的部分,生成key有好多种做法,这里我介绍三种
  (1)命令行:可以使用openssl进行生成公钥和私钥 openssl genrsa -out key.pem 1024             -out 指定生成文件,此文件包含公钥和私钥两部分,所以即可以加密,也可以解密 1024 生成密钥的长度
  (2)使用网站:生成密钥的网站
  (3)使用代码:可以指定生成密钥的长度,最低是512 public static KeyPair buildKeyPair() throws NoSuchAlgorithmException { final int keySize = 2048;     KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);     keyPairGenerator.initialize(keySize); return keyPairGenerator.genKeyPair(); }
  加密
  有了密钥,就可以进行加密的操作了,接下来就介绍关于RSA的加密操作,非常简单只要传进来公钥和需要加密的数据即可。 public static byte[] encrypt(PublicKey publicKey, String message) throws Exception {         Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);         cipher.init(Cipher.ENCRYPT_MODE, publicKey);  return cipher.doFinal(message.getBytes(UTF8));     }
  解密 --- 解密 public static byte[] decrypt(PrivateKey privateKey, byte [] encrypted) throws Exception {     Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);     cipher.init(Cipher.DECRYPT_MODE, privateKey);  return cipher.doFinal(encrypted); }
  加签  * 使用RSA签名  */ private static String signWithRSA(String content, PrivateKey privateKey) throws Exception {     Signature signature = Signature.getInstance("SHA1WithRSA");     signature.initSign(privateKey);     signature.update(content.getBytes("utf-8"));     byte[] signed = signature.sign(); return base64Encode(signed); }
  验签  * 使用RSA验签  */ private static boolean checkSignWithRSA(String content, PublicKey publicKey,String sign) throws Exception {     Signature signature = Signature.getInstance("SHA1WithRSA");     signature.initVerify(publicKey);     signature.update(content.getBytes("utf-8")); return signature.verify(base64Decode(sign)); }
  在加签验签的时候需要传入一个数字签名标准,我们这里填的是SHA1WithRSA ,它的意思是用SHA算法进行签名,用RSA算法进行加密。
  算法说明:在对进行SHA1算法进行摘要计算后,要求对计算出的摘要进行处理,而不是直接进行RSA算法进行加密。要求把SHA1摘要的数据进行压缩到20个字节。在前面插入15个字节标示数据。所以结构如下
  最后进行RSA加密。所以我们填写的XXXWithRSA,这个XXX代表的就是使用什么摘要算法进行加签,至于摘要算法是什么,随后会有详细的说明。
  调用实验一下     KeyPair keyPair = buildKeyPair();      byte[] encryptData = encrypt(keyPair.getPublic(), "不学无数");      System.out.println(String.format("加密后的数据:%s",base64Encode(encryptData)));      System.out.println(String.format("解密后的数据:%s",new String(decrypt(keyPair.getPrivate(),encryptData),UTF8)));  String context = "加签的字符串";  String sign = signWithRSA(context, keyPair.getPrivate());      System.out.println(String.format("生成的签名:%s",sign));  Boolean checkSignWithRSA = checkSignWithRSA(context, keyPair.getPublic(), sign);      System.out.println(String.format("校验的结果:%s",checkSignWithRSA.toString())); }
  输出为 6YrYqd7fdast/m443qQreRLxdQFScwvCvj9g1YnPzbU2Q/jIwqAPopTyPHNNngBmFki+R/6V4DYt HA5gniaUMYzynHdD+/W+x8ZYmwiuuS63+7wXqL36aLKe0H50wELOpSn45Gvni8u+5zPIoHV7PBiz trCnQvne5LxFKDprrS3td1/76qyupFd+Ul3hsd+gjbAyN2MlXcAFMrGVaRkopWwc9hP1BsPvS52q /8jOVdbeyU9BziVhViz1V0TtGW8bfbEnIStc3Q== 解密后的数据:不学无数 生成的签名:wvUXtr2UI0tUXmyMTTUBft8oc1dhvtXSBrFFetI5ZoxMm91TbXRWD31Pgqkg72ADxx9TEOAM3Bm1 kyzfBCZZpoq6Y9SM4+jdJ4sMTVtw0wACPglnPDAGs8sG7nnLhXWNQ1Y4pl4ziY6uLxF1TzQLFTxu NAS7nyljbG69wrb9R3Sv5t8r1I54rYCVGSVFmTrGf+dSCjxABZv6mH8nygVif7zN1vU1+nSDKcON Vtrpv0xCQHVBqnHPA6OiDm5GzBQxjD5aQt8mfgv8JJrB52TEa4JPYoC5Zw4JHlL++OvPwMpJgnuG yg5vnWhxE2ncTzM+/pZ+CnXF2Dqv/JMQOfX6tA== 校验的结果:true 4摘要算法
  数据摘要算法是密码学算法中非常重要的一个分支,它通过对所有数据提取指纹信息以实现数据签名、数据完整性校验等功能,由于其不可逆性,有时候会被用做敏感信息的加密。数据摘要算法也被称为哈希(Hash)算法或散列算法。
  消息摘要算法的主要特征是加密过程不需要密钥,并且经过加密的数据无法被解密,只有输入相同的明文数据经过相同的消息摘要算法才能得到相同的密文。(摘要可以比方为指纹,消息摘要算法就是要得到文件的唯一职位) 4.1 特点
  无论输入的消息有多长,计算出来的消息摘要的长度总是固定的。一般地,只要输入的消息不同,对其进行摘要以后产生的摘要消息也必不相同;但相同的输入必会产生相同的输出。只能进行正向的信息摘要,而无法从摘要中恢复出任何的消息,甚至根本就找不到任何与原信息相关的信息(不可逆性)。
  好的摘要算法,没有人能从中找到"碰撞"或者说极度难找到,虽然"碰撞"是肯定存在的(碰撞即不同的内容产生相同的摘要)。 4.2 应用
  一般地,把对一个信息的摘要称为该消息的指纹或数字签名。数字签名是保证信息的完整性和不可否认性的方法。数据的完整性是指信宿接收到的消息一定是信源发送的信息,而中间绝无任何更改;信息的不可否认性是指信源不能否认曾经发送过的信息。其实,通过数字签名还能实现对信源的身份识别(认证),即确定"信源"是否是信宿意定的通信伙伴。数字签名应该具有唯一性,即不同的消息的签名是不一样的;同时还应具有不可伪造性,即不可能找到另一个消息,使其签名与已有的消息的签名一样;还应具有不可逆性,即无法根据签名还原被签名的消息的任何信息。这些特征恰恰都是消息摘要算法的特征,所以消息摘要算法适合作为数字签名算法。
  有哪些具体的消息摘要算法?
  CRC8、CRC16、CRC32:CRC(Cyclic Redundancy Check,循环冗余校验)算法出现时间较长,应用也十分广泛,尤其是通讯领域,现在应用最多的就是 CRC32 算法,它产生一个4字节(32位)的校验值,一般是以8位十六进制数,如FA 12 CD 45等。CRC算法的优点在于简便、速度快,严格的来说,CRC更应该被称为数据校验算法,但其功能与数据摘要算法类似,因此也作为测试的可选算法。
  MD2 、MD4、MD5:这是应用非常广泛的一个算法家族,尤其是 MD5(Message-Digest Algorithm 5,消息摘要算法版本5),它由MD2、MD3、MD4发展而来,由Ron Rivest(RSA公司)在1992年提出,目前被广泛应用于数据完整性校验、数据(消息)摘要、数据加密等。MD2、MD4、MD5 都产生16字节(128位)的校验值,一般用32位十六进制数表示。MD2的算法较慢但相对安全,MD4速度很快,但安全性下降,MD5比MD4更安全、速度更快。
  SHA1、SHA256、SHA384、SHA512:SHA(Secure Hash Algorithm)是由美国专门制定密码算法的标准机构——美国国家标准技术研究院(NIST)制定的,SHA系列算法的摘要长度分别为:SHA为20字节(160位)、SHA256为32字节(256位)、 SHA384为48字节(384位)、SHA512为64字节(512位),由于它产生的数据摘要的长度更长,因此更难以发生碰撞,因此也更为安全,它是未来数据摘要算法的发展方向。由于SHA系列算法的数据摘要长度较长,因此其运算速度与MD5相比,也相对较慢。
  RIPEMD、PANAMA、TIGER、ADLER32 等: RIPEMD是Hans Dobbertin等3人在对MD4,MD5缺陷分析基础上,于1996年提出来的,有4个标准128、160、256和320,其对应输出长度分别为16字节、20字节、32字节和40字节。TIGER由Ross在1995年提出。Tiger号称是最快的Hash算法,专门为64位机器做了优化。 4.3 实战演练
  在单独的使用摘要算法时我们通常使用的MD5算法,所以我们这里就单独说明使用Java实现MD5算法。 try { // 生成一个MD5加密计算摘要         MessageDigest md = MessageDigest.getInstance("MD5"); // 计算md5函数         md.update(str.getBytes()); // digest()最后确定返回md5 hash值,返回值为8为字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符 // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值 return new BigInteger(1, md .digest()).toString(16);     } catch (Exception e) { throw new Exception("MD5加密出现错误,"+e.toString());     } } 5参考文章
  https://zhuanlan.zhihu.com/p/20064358
  https://time.geekbang.org/column/article/224701
  https://my.oschina.net/OutOfMemory/blog/3131916
  https://www.zz-news.com/com/zhongshanfengyu/news/itemid-67474...
  https://www.hbhncj.com/article-53-3443-1.html
  https://www.zhihu.com/question/33645891

大众车和丰田车有什么差别?哪个更适合成为家用车?我开过大众桑塔纳,也开过丰田皇冠,才知中国的大众,世界的丰田误导很多人,奉劝要买大众丰田的人要三思,如果必须二选其一,20万以下选大众,20万以上选丰田,错不了!大众是德系车的代表孩子不写作业,顶嘴,家长忽悠孩子,说他被学校开除了,可行不?谁让这家长往日无明的隐形小忽悠促长孩子叛逆成惯性,还没觉察到尽然继续忽悠至尽,接下来怎么回应是孩子的自然而然的事,什么果受是家长自己应该接受与反省的事,行不行怎么行,还请这类家长们身边很多人生了二胎,动摇了怎么办,二胎真有大家说的那么辛苦吗?我08年生的我家老大,那个时候还有计划生育,不允许生二胎,大儿子出生时我想着一胎是儿子我就不用生二胎了,国家不允许,儿子三四岁的时候入学了,我也找了份工作,身边很多人都偷着生二胎了IG到底怎么培养JackeyLove的?不是ig培养的他,而是他本身就强,去ig就打首发了,而且不像小狗那样吃资源,像巅峰时期的小伞,隐身AD默默发育,打团收割。就冲那个闪现,在世界大赛上,如此重要的比赛,背后就是国服的李世民纳了弟妹杨氏,而没有纳嫂子郑观音吗?为什么?因为他不敢。别说他了,搁你身上,你也不敢纳。李世民在男女之事上,一直很随便。不仅纳了弟妹,大破突厥时,还跟隋炀帝60岁的萧皇后风月一场。但他真不敢纳嫂子。郑观音是他惹不起的女人。对明代最有权势的锦衣卫首领陆炳,为何能得到善终并保全家族?明嘉靖三十九年(1560年)十二月,京师大雪,在一片萧瑟之下,嘉靖帝得到了一个悲伤的消息太保少傅太子太傅左都督掌锦衣卫事陆炳暴卒,时年五十一。得知这个和自己一起长大又一起从安陆进京苹果8p,3600现在还值不值得买?感谢邀请苹果8p,3600现在还值不值得买?现在已经是2021年的11月份了,实际3600元左右,我们确实可以选择到iPhone12的64G版本了,这相比iPhone8plus来说怎么样才能屏蔽手机摇一摇就进入别的软件?这是软件内部设置的广告推广。现在一些手机有这种智能屏蔽功能,有些手机还不具备这种功能。1。测试手机华为手机具体设置如下设置应用与服务应用启动管理设置手动管理里面有一个允许关联启动可2手的小蚂蚁251到底值不值得购买?要看这个二手的小蚂蚁是哪一类车。1营转非,就是原来的营运车辆(共享汽车)转为非营运车辆,这种车有强制报废年限。2非营转非,原来是公司户,转为个人户,这种车没有强制报废年限。3个人二八代凯美瑞2。0自吸值不值得购买?我就是买的21款八代2。0,先介绍一下背景资料,上辆车是06年的八代思域,30多岁不到40,一个孩子,家庭年收入差不多40多不到50,闲钱有七位数,四线城市,因为住市中心堵车也很严最近比较火的区块链到底值不值得去投资?很高兴能回答您这个问题。万事万物都有其双面性,要看你怎么去理解。在您的问题中您提出了是否应该投资区块链的疑问,这要看您从哪个角度去思考这个问题。如果从笔者的思想角度考虑,遇到区块链
阳康之后,什么情况不能喝咖啡你阳康了吗?第一波感染新冠病毒的已经好转,基本已经恢复或者在恢复期,这时候不仅仅要要注意饮食的变化,更要关注身体的变化,潜在风险还是存在,尤其是本身有基础性疾病人员。今天我们说一下你说蔚来不行,但它卖的是真好尽管已经2023年了,但相信很多燃油车拥趸对目前新势力造车的前景依旧是不太看好,尤其是像蔚来这种互联网造车企业。我经常会刷到李斌的一些个人言论,在被剪辑后传播到各大视频平台上,引起优势与难点,浅析宁德时代CTC一体化智能底盘技术如今的CTC一体化底盘,是电动汽车动力电池的3。0技术版本,将电池电芯与汽车底盘彻底融合在一起,优势明显的同时,难度自然也不小。1月10日,哪吒汽车与宁德时代在一体化智能底盘技术上7680X660分辨率!车载超级大屏幕即将普及?当下,很多新能源汽车为了标榜自己智能的性能,在车内采用多块大屏幕,实现几乎0实体按键的状态。但是,这些屏幕并非一整块,而是多块拼接在一起,即便是上一代奔驰S级这种旗舰车型,也并没有李晓春等Sr和SmNd同位素体系对热液蚀变过程的响应放射性同位素体系RbSr和SmNd被广泛用来进行地质示踪和定年,在地球科学研究中具有重要的应用。运用放射性同位素体系进行示踪或定年的前提是其在地质过程中保持封闭。然而自然界的矿物和深圳湾实验室科技创新人物巡礼陈杰安在手性化学中探秘寻踪来源读特人物简介陈杰安,于2010年获得中山大学理学学士学位,同年攻读北京大学有机化学方向博士学位,获得2015年北京大学优秀毕业生荣誉。随后,以联合培养的模式于北京大学深圳研究生ES在大数据中的应用一相关软件介绍1。ElasticsearchElasticsearch,简称为ES,是一个分布式高扩展高实时的搜索与数据分析引擎。它能很方便的使大量数据具有搜索分析和探索的能力。无理想L8实车图,售35。98万起外观大气,续航达1315km近几年,理想新能源汽车在我国混的可谓是风生水起,近日,有媒体曝光了理想L8的实车图,新车在此前已经正式上市,并且推出两款车型可选售价为35。98万元39。98万元。新车外观设计时尚华为云联合东方通打造国产中间件,助力信创事业发展当今时代,信创产业是数据安全网络安全的基础,也是新基建的重要内容,将成为拉动经济发展的重要抓手之一,而中间件是信创产业基础软件不可或缺的重要组成部分。它是一类独立的系统软件服务程序redis介绍redis学习Redis现在基本上java项目都在使用,Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串哈希表列表集永辉超市入选2022中国十大人气超市日前,零售商业财经发布2022中国十大人气超市榜单,永辉超市凭借夯实的综合实力脱颖而出,成功登榜。据悉,本次评选从企业实力品牌荣誉消费者口碑企业行业内排名等多维度出发,并结合12月