系列文章目录提示这里可以添加系列文章的所有文章的目录目录需要自己手动添加文章目录系列文章目录前言加密算法单项散列函数MD5、SHA1、SHA2对称加密AES、DES、3DES非对称加密RSA、DSA、ECCJCAJCE编码技术Hex编码与解码Base64编码与解码URL编码与解码前言JCA (Java Cryptography Architecture) - 提供可插拔的密码服务提供者框架定义密码学原语的 SPI。java.security.* (Provider, SecureRandom, MessageDigest, Signature)JCE (Java Cryptography Extension) - 提供具体的密码算法实现对称/非对称加密、密钥协商、MAC。javax.crypto.* (Cipher, KeyGenerator, SecretKey)加密算法单项散列函数MD5、SHA1、SHA2单向散列函数/消息摘要函数/哈希函数是一种能够从任意长度的输入数据生成固定长度、唯一性高的输出值称为散列值、哈希值或消息摘要的数学函数。加密过程不需要私钥散列计算速度快非常高效。著名算法 RSA 公司的MD5算法和SHA-1算法及其大量的变体。算法名称输出长度 (位)简要说明现状MD5128曾广泛使用速度快。已不安全存在严重碰撞漏洞不应用于安全目的。SHA-1160曾用于SSL/TLS证书、Git版本控制等。已被破解碰撞攻击主流环境均已弃用。SHA-2 系列224/256384/512目前最广泛使用和推荐的算法族。SHA-256和SHA-512是最常用的变体。安全广泛推荐。是TLS、SSL、PGP、SSH等协议和比特币的基础。SHA-3 系列224/256384/512采用与SHA-2不同的内部结构Keccak算法作为SHA-2的备份和补充。安全正在逐步被采用。提供了与SHA-2不同的数学基础增加多样性。核心特性包括单向性​ 从输入计算散列值很容易但要从散列值反向推导出原始输入在计算上不可行。抗碰撞性​ 很难找到两个不同的输入产生相同的散列值。雪崩效应​ 原始输入即使发生微小的改动如修改一个比特产生的散列值也会发生巨大的、看似随机的变化。主要作用数据完整性校验​ 验证文件、消息在传输或存储过程中是否被篡改。发送方计算散列值并随数据一起发送接收方重新计算并与收到的散列值比对。密码存储​ 不存储用户明文密码而是存储其散列值。登录时比较输入密码的散列值是否与存储的一致。数字签名​ 通常是对消息的散列值进行签名而非对完整消息签名以提高效率。消息认证码​ 是构建消息认证码HMAC的基础。区块链与工作量证明​ 是比特币等区块链技术的核心组件。MD5的安全性和改进可通过【暴力碰撞】解密MD5的强抗碰撞性已经被证实攻破即对于重要数据不应该再继续使用MD5加密。MD5解密网站并不是对加密后的数据进行解密而是数据库中存在大量的加密后的数据对用户输入的数据进行匹配也叫暴力碰撞匹配到与之对应的数据就会输出并没有对应的解密算法。可以对MD5进行改进加大破解的难度典型的加大解密难度的方式有一下几种加盐Salt在明文的固定位置插入随机串然后再进行MD5先加密后乱序先对明文进行MD5然后对加密得到的MD5串的字符进行乱序先乱序后加密先对明文字符串进行乱序处理然后对得到的串进行加密先乱序再加盐再MD5等HMac消息认证码HMAC-MD5、HMAC-SHA1消息的发送者和接收者有一个共享密钥发送者使用共享密钥对消息加密计算得到MAC值消息认证码然后把消息和消息认证码一起发送出去消息接收者收到后也使用共享密钥对消息加密计算得到MAC值比较两个MAC值是否一致如果一致则信任。也可以进行多次的md5运算总之就是要加大破解的难度。对称加密AES、DES、3DES对称加密是指双方持有相同的密钥进行通信加密解密使用相同的密钥速度快可逆。经典算法DES 数据加密标准3DES 使用3个密钥对消息进行密钥1·加密密钥2·解密密钥3·加密AES 高级加密标准对称加密存在的问题密钥的传递和保存是一个问题参与加密和解密的双方使用的密钥是一样的这样密钥就很容易泄露。很明显对称加密主要取决于秘钥的安全性数据传输的过程中如果秘钥被别人破解的话以后的加解密就将失去意义。对称密码体制中只有一种密钥并且是非公开的如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全而非对称密钥体制有两种密钥其中一个是公开的这样就可以不需要像对称密码那样传输对方的密钥了。非对称加密RSA、DSA、ECC非对称加密公开密钥加密是为了解决对称加密中的安全问题而诞生一个对外开放的公钥(public key)另一个自己拥有的私钥(private key)。公钥加密的数据只能用私钥解密。私钥加密的数据只能用公钥解密。算法复杂加密处理安全但加密速度慢。非对称加密存在的安全问题原理上看非对称加密非常安全客户端用公钥进行加密服务端用私钥进行解密数据传输的只是公钥原则上看就算公钥被人截获也没有什么用因为公钥只是用来加密的那还存在什么问题呢那就是经典的中间人攻击。造成中间人攻击的直接原因客户端没办法判断公钥信息的正确性。解决中间人攻击对公钥进行数字签名。数字签名需要严格验证发送的身份信息openssl 生成 私钥和公钥生成强度是 512 的 RSA 私钥openssl genrsa -out private.pem 512以明文输出私钥内容openssl rsa -in private.pem -text -out private.txt校验私钥文件openssl rsa -in private.pem -check从私钥中提取公钥openssl rsa -in private.pem -out public.pem -outform PEM -pubout以明文输出公钥内容openssl rsa -in public.pem -out public.txt -pubin -pubout -text使用公钥加密小文件openssl rsautl -encrypt -pubin -inkey public.pem -in msg.txt -out msg.bin使用私钥解密小文件openssl rsautl -decrypt -inkey private.pem -in msg.bin -out a.txt将私钥转换成 DER 格式openssl rsa -in private.pem -out private.der -outform der将公钥转换成 DER 格式openssl rsa -in public.pem -out public.der -pubin -outform derJCAJCE编码技术编码作用将字节数据转换为等效的纯英文表示方便传输与存储。编码的本质作用都是将字节数据转换为等效的纯英文形式主要用在那些不方便查看、存储或传输原始字节数据的地方。比如在html中因为html本身就是纯文本的不能直接放入原始字节数据这时我们可以将一些小图标(非文本数据)通过base64编码的方式内嵌到html中以使得html页面与图标数据能在一次网络交互中返回这种方案也称Data URI。Hex编码与解码Hex 全称是Intel HEX。Hex文件是由一行行符合Intel HEX文件格式的文本所构成的ASCII文本文件。在Intel HEX文件中每一行包含一个HEX记录。这些记录由对应机器语言码和/或常量数据的十六进制编码数字组成。如下99、105、2247编码之后的数据为“6369e007”是一个字符串。Base64编码与解码Base64编码URL安全(将Base64中的URL非法字符’‘和’/‘转为’-‘和’_, 见RFC3548)。注意字符串最后加上了“”其意思表示字符串编码的结束。由于我们可能对各种各样的数据进行加密比如视频、音频、文本文件等所以加密之前我们需要统一文件类型然后再进行加密处理。Base64编码原理将所有字符串转换成ASCII码将ASCII码转换成8位二进制将二进制三位归成一组不足三位在后边补0再按每组6位拆成若干组统一在6位二进制后不足8位的补0将补0后的二进制转换成十进制 从Base64编码表取出十进制对应的Base64编码。若原数据长度不是3的倍数时且剩下1个输入数据则在编码结果后加2个若剩下2个输入数据则在编码结果后加1个。如上面的例子原数据为A数据长度为11 % 3 1 后面加两个原数据为bc数据长度为22 % 3 2 后面加一个。Base64编码的特点可以将任意的二进制数据进行Base64编码。所有的数据都能被编码为并只用65个字符就能表示的文本文件。编码后的65个字符包括AZ,az,0~9,,/,对文件或字符串进行Base64编码后将比原始大小增加33%。能够逆运算不够安全但却被很多加密算法作为编码方式java.util.Base64工具类importjava.util.Base64;importjava.nio.charset.StandardCharsets;publicclassBase64Example{publicstaticvoidmain(String[]args){StringoriginalTextHello, World! 你好世界;StringoriginalBinaryDataBinary Data: \u00A9\u00AE;// --- 获取编码器/解码器实例 ---// 1. 基本编码器 (RFC 4648)Base64.EncoderbasicEncoderBase64.getEncoder();Base64.DecoderbasicDecoderBase64.getDecoder();// 2. URL安全的编码器 (用 - 和 _ 替换 和 /)Base64.EncoderurlEncoderBase64.getUrlEncoder();Base64.DecoderurlDecoderBase64.getUrlDecoder();// 3. MIME友好的编码器 (每76字符换行使用CRLF)Base64.EncodermimeEncoderBase64.getMimeEncoder();Base64.DecodermimeDecoderBase64.getMimeDecoder();// --- 对字符串进行基本Base64编码/解码 ---// 编码StringencodedStringbasicEncoder.encodeToString(originalText.getBytes(StandardCharsets.UTF_8));System.out.println(Base64 编码: encodedString);// 解码byte[]decodedBytesbasicDecoder.decode(encodedString);StringdecodedStringnewString(decodedBytes,StandardCharsets.UTF_8);System.out.println(Base64 解码: decodedString);// --- URL安全编码示例 ---StringurlToEncodehttps://example.com/path?namevaluedataabc/;StringurlEncodedurlEncoder.encodeToString(urlToEncode.getBytes(StandardCharsets.UTF_8));System.out.println(URL安全编码: urlEncoded);// 和 / 会被替换// --- 直接编码/解码字节数组 ---byte[]binaryDataoriginalBinaryData.getBytes(StandardCharsets.UTF_8);byte[]encodedBytesbasicEncoder.encode(binaryData);byte[]decodedBinaryDatabasicDecoder.decode(encodedBytes);// --- 使用流式处理 (适用于大文件) ---// Base64.Encoder.wrap(OutputStream) - 对输出流进行Base64编码// Base64.Decoder.wrap(InputStream) - 对输入流进行Base64解码}}URL编码与解码当URL地址里包含非西欧字符的字符串时浏览器都会将这些非西欧字符串转换成application/x-www-form-urlencoded MIME 字符串。在开发过程中我们可能涉及将普通字符串和这种特殊字符串的相关转换这就需要使用 URLDecoder 和 URLEncoder类进行实现。