加解密篇 - 非对称加密算法 (RSA、DSA、ECC、DH)
目录简介RSA算法DSA算法ECC算法DH算法1. 简介1.1 概念非对称加密需要两个密钥公钥 (publickey) 和私钥 (privatekey)。公钥和私钥是一对如果用公钥对数据加密那么只能用对应的私钥解密。如果用私钥对数据加密只能用对应的公钥进行解密。因为加密和解密用的是不同的密钥所以称为非对称加密。非对称加密算法的保密性好它消除了最终用户交换密钥的需要。但是加解密速度要远远慢于对称加密在某些极端情况下甚至能比对称加密慢上1000倍。1.2 特点算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥并且是非公开的如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全而非对称密钥体制有两种密钥其中一个是公开的这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。1.3 工作原理(1) A 要向 B 发送信息A 和 B 都要产生一对用于加密和解密的公钥和私钥。(2) A 的私钥保密A 的公钥告诉 BB 的私钥保密B 的公钥告诉 A。(3) A 要给 B 发送信息时A 用 B 的公钥加密信息因为 A 知道 B 的公钥。(4) A 将这个消息发给 B (已经用 B 的公钥加密消息)。(5) B 收到这个消息后B 用自己的私钥解密 A 的消息。其他所有收到这个报文的人都无法解密因为只有 B 才有 B 的私钥。1.4 主要算法RSA:经典的公钥算法1978年由Ronald Riverst、Adidas Shamir 、LeonardAdleman 共同提出三人于2002年因此获得图灵奖。算法利用了对大数进行质因子分解困难的特性但目前还没有数学证明两者难度等价或许存在未知算法在不进行大数分解的前提下解密Elgamal:由Taher ElGamal 设计利用了模运算下求离散对数困难的特性。被应用在PGP等安全工具中Diffie -Hellman 密钥交换基于离散对数无法快速求解可以在不安全的通道上双方协商一个公共密钥SM2(ShangMi 2):国家商用密码算法由国家密码管理局于2010年12月17日发布同样基于椭圆曲线算法加密强度优于RSA系列算法椭圆曲线算法( Elliptic Curve Cryptography,ECC):现代备受关注的算法系列基于对椭圆曲线上特定点进行特殊乘法逆运算难以计算的特性。最早在1985年由Neal Koblitz和 Victor Miller 分别独立提出。ECC系列算法一般被认为具备较高的安全性但加解密计算过程往往比较费时RSA、Elgamal、背包算法、Rabin、D-H、ECC (椭圆曲线加密算法)。使用最广泛的是 RSA 算法Elgamal 是另一种常用的非对称加密算法。1.5 应用场景(1) 信息加密收信者是唯一能够解开加密信息的人因此收信者手里的必须是私钥。发信者手里的是公钥其它人知道公钥没有关系因为其它人发来的信息对收信者没有意义。(2) 登录认证客户端需要将认证标识传送给服务器此认证标识 (可能是一个随机数) 其它客户端可以知道因此需要用私钥加密客户端保存的是私钥。服务器端保存的是公钥其它服务器知道公钥没有关系因为客户端不需要登录其它服务器。(3) 数字签名数字签名是为了表明信息没有受到伪造确实是信息拥有者发出来的附在信息原文的后面。就像手写的签名一样具有不可抵赖性和简洁性。简洁性对信息原文做哈希运算得到消息摘要信息越短加密的耗时越少。不可抵赖性信息拥有者要保证签名的唯一性必须是唯一能够加密消息摘要的人因此必须用私钥加密 (就像字迹他人无法学会一样)得到签名。如果用公钥那每个人都可以伪造签名了。(4) 数字证书问题起源对1和3发信者怎么知道从网上获取的公钥就是真的没有遭受中间人攻击这样就需要第三方机构来保证公钥的合法性这个第三方机构就是 CA (Certificate Authority)证书中心。CA 用自己的私钥对信息原文所有者发布的公钥和相关信息进行加密得出的内容就是数字证书。信息原文的所有者以后发布信息时除了带上自己的签名还带上数字证书就可以保证信息不被篡改了。信息的接收者先用 CA给的公钥解出信息所有者的公钥这样可以保证信息所有者的公钥是真正的公钥然后就能通过该公钥证明数字签名是否真实了。这个的实际应用可以看看我之前的文章网络篇 - https协议中的数据是否需要二次加密里面讲的比较详细。RSA算法2.1 简介RSA 是目前最有影响力的公钥加密算法该算法基于一个十分简单的数论事实将两个大素数相乘十分容易但想要对其乘积进行因式分解却极其困难因此可以将乘积公开作为加密密钥即公钥而两个大素数组合成私钥。公钥是可发布的供任何人使用私钥则为自己所有供解密之用。2.2 工作流程A 要把信息发给 B 为例确定角色A 为加密者B 为解密者。首先由 B 随机确定一个 KEY称之为私钥将这个 KEY 始终保存在机器 B 中而不发出来然后由这个 KEY 计算出另一个 KEY称之为公钥。这个公钥的特性是几乎不可能通过它自身计算出生成它的私钥。接下来通过网络把这个公钥传给 AA 收到公钥后利用公钥对信息加密并把密文通过网络发送到 B最后 B 利用已知的私钥就能对密文进行解码了。以上就是 RSA 算法的工作流程。2.3 运算速度由于进行的都是大数计算使得 RSA 最快的情况也比 DES 慢上好几倍无论是软件还是硬件实现。速度一直是 RSA 的缺陷。一般来说只用于少量数据加密。RSA 的速度是对应同样安全级别的对称密码算法的1/1000左右。比起 DES 和其它对称算法来说RSA 要慢得多。实际上一般使用一种对称算法来加密信息然后用 RSA 来加密比较短的公钥然后将用 RSA 加密的公钥和用对称算法加密的消息发送给接收方。这样一来对随机数的要求就更高了尤其对产生对称密码的要求非常高否则的话可以越过 RSA 来直接攻击对称密码。2.4 公钥传递安全和其它加密过程一样对 RSA 来说分配公钥的过程是非常重要的。分配公钥的过程必须能够抵挡中间人攻击。假设 A 交给 B 一个公钥并使 B 相信这是A 的公钥并且 C 可以截下 A 和 B 之间的信息传递那么 C 可以将自己的公钥传给 BB 以为这是 A 的公钥。C 可以将所有 B 传递给 A 的消息截下来将这个消息用自己的密钥解密读这个消息然后将这个消息再用 A 的公钥加密后传给 A。理论上 A 和 B 都不会发现 C 在偷听它们的消息今天人们一般用数字认证来防止这样的攻击。2.5 攻击(1) 针对 RSA 最流行的攻击一般是基于大数因数分解。1999年RSA-155 (512 bits) 被成功分解花了五个月时间约8000 MIPS 年和224 CPU hours 在一台有3.2G 中央内存的 Cray C916计算机上完成。RSA-158 表示如下39505874583265144526419767800614481996020776460304936454139376051579355626529450683609727842468219535093544305870490251995655335710209799226484977949442955603 3388495837466721394368393204672181522815830368604993048084925840555281177× 116588234066712599031483765583832708181310122581463926004395209941313443341629245361392009年12月12日编号为 RSA-768 (768 bits, 232 digits) 数也被成功分解。这一事件威胁了现通行的1024-bit 密钥的安全性普遍认为用户应尽快升级到2048-bit 或以上。RSA-768表示如下1230186684530117755130494958384962720772853569595334792197322452151726400507263657518745202199786469389956474942774063845925192557326303453731548268507917026122142913461670429214311602221240479274737794080665351419597459856902143413 3347807169895689878604416984821269081770479498371376856891 2431388982883793878002287614711652531743087737814467999489× 3674604366679959042824463379962795263227915816434308764267 6032283815739666511279233373417143396810270092798736308917(2) 秀尔算法量子计算里的秀尔算法能使穷举的效率大大的提高。由于 RSA 算法是基于大数分解 (无法抵抗穷举攻击)因此在未来量子计算能对 RSA 算法构成较大的威胁。一个拥有 N 量子位的量子计算机每次可进行2^N 次运算理论上讲密钥为1024位长的 RSA 算法用一台512量子比特位的量子计算机在1秒内即可破解。2.6 例子private static final String ALGO RSA; private static final String CHARSET UTF-8; /* * 用于存储随机产生的公钥与私钥 */ private static MapInteger, String KEY_CACHE new HashMap(); /** * 随机生成密钥对 * * throws NoSuchAlgorithmException */ private static void generateKeyPair() throws NoSuchAlgorithmException { // KeyPairGenerator 类用于生成公钥和私钥对基于RSA算法生成对象 KeyPairGenerator keyPairGen KeyPairGenerator.getInstance(ALGO); // 初始化密钥对生成器密钥大小为 96-1024 位 keyPairGen.initialize(1024, new SecureRandom()); // 生成一个密钥对保存在 keyPair 中 KeyPair keyPair keyPairGen.generateKeyPair(); // 得到私钥 RSAPrivateKey privateKey (RSAPrivateKey) keyPair.getPrivate(); // 得到公钥 RSAPublicKey publicKey (RSAPublicKey) keyPair.getPublic(); String publicKeyString new String(Base64.getEncoder().encode(publicKey.getEncoded())); // 得到私钥字符串 String privateKeyString new String(Base64.getEncoder().encode((privateKey.getEncoded()))); // 将公钥和私钥保存到 Map KEY_CACHE.put(0, publicKeyString); KEY_CACHE.put(1, privateKeyString); } /** * RSA公钥加密 * * param data 加密字符串 * param publicKey 公钥 * return 密文 * throws Exception 加密过程中的异常信息 */ private static String encrypt(String data, String publicKey) throws Exception { // base64 编码的公钥 byte[] decoded Base64.getDecoder().decode(publicKey); RSAPublicKey pubKey (RSAPublicKey) KeyFactory.getInstance(ALGO).generatePublic(new X509EncodedKeySpec(decoded)); // RSA加密 Cipher cipher Cipher.getInstance(ALGO); // 公钥加密 cipher.init(Cipher.ENCRYPT_MODE, pubKey); return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes(CHARSET))); } /** * RSA私钥解密 * * param data 加密字符串 * param privateKey 私钥 * return 铭文 * throws Exception 解密过程中的异常信息 */ private static String decrypt(String data, String privateKey) throws Exception { byte[] inputByte Base64.getDecoder().decode(data.getBytes(CHARSET)); // base64 编码的私钥 byte[] decoded Base64.getDecoder().decode(privateKey); RSAPrivateKey priKey (RSAPrivateKey) KeyFactory.getInstance(ALGO).generatePrivate(new PKCS8EncodedKeySpec(decoded)); // RSA 解密 Cipher cipher Cipher.getInstance(ALGO); // 私钥解密 cipher.init(Cipher.DECRYPT_MODE, priKey); return new String(cipher.doFinal(inputByte)); } public static void main(String[] args) { String originData hellp Test Asymmetric encrypt!; try { generateKeyPair(); String encryData encrypt(originData, KEY_CACHE.get(0)); System.out.println(encryData encryData); String decryData decrypt(encryData, KEY_CACHE.get(1)); System.out.println(decryData decryData); } catch (Exception e) { e.printStackTrace(); } }执行输出encryData Agp72Awcbwy9/8qCFN7VBEwek9LRhjdOqT6JA3MaLOIrEc/VR85vW/q/dL4WOl6ELlyd0L4dieikfw0U94FuHlyTItEen33lzRszWxjH8ElSH1/W/3SoAm0r7qRdJGoHpRXNGwsnoS77mhYtn743txX1O4bjIdZrLwQZB/6IdecryData hellp Test Asymmetric encrypt!DSA算法3.1 简介DSA (Digital Signature Algorithm) 是 Schnorr 和 ElGamal 签名算法的变种被美国 NIST 作为 DSS (DigitalSignature Standard)。 DSA 是基于整数有限域离散对数难题的。简单的说这是一种更高级的验证方式用作数字签名。不单单只有公钥、私钥还有数字签名。私钥加密生成数字签名公钥验证数据及签名如果数据和签名不匹配则认为验证失败。数字签名的作用就是校验数据在传输过程中不被修改数字签名是单向加密的升级。3.2 处理过程(1) 使用消息摘要算法将发送数据加密生成数字摘要。(2) 发送方用自己的私钥对摘要再加密形成数字签名。(3) 将原文和加密的摘要同时传给对方。(4) 接受方用发送方的公钥对摘要解密同时对收到的数据用消息摘要算法产生同一摘要。(5) 将解密后的摘要和收到的数据在接收方重新加密产生的摘要相互对比如果两者一致则说明在传送过程中信息没有破坏和篡改。否则则说明信息已经失去安全性和保密性。具体可以看这篇网络篇 - https协议中的数据是否需要二次加密3.3 例子*/ DSA安全编码组件 */ public abstract class DSACoder extends Coder{public static final String ALGORITHMDSA;/** * 默认密钥字节数 * *pre* DSA * Default Keysize1024* Keysize must be a multiple of64, ranging from512to1024(inclusive). */pre*/ private static final int KEY_SIZE1024;/** * 默认种子 */ private static final String DEFAULT_SEED0f22507a10bbddd07d8a3082122966e3;private static final String PUBLIC_KEYDSAPublicKey;private static final String PRIVATE_KEYDSAPrivateKey;/** * 用私钥对信息生成数字签名 * * param data * 加密数据 * param privateKey * 私钥 * * return * throws Exception */ public static String sign(byte[]data, String privateKey)throws Exception{// 解密由base64编码的私钥 byte[]keyBytesdecryptBASE64(privateKey);// 构造PKCS8EncodedKeySpec对象 PKCS8EncodedKeySpec pkcs8KeySpecnew PKCS8EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactoryKeyFactory.getInstance(ALGORITHM);// 取私钥匙对象 PrivateKey priKeykeyFactory.generatePrivate(pkcs8KeySpec);// 用私钥对信息生成数字签名 Signature signatureSignature.getInstance(keyFactory.getAlgorithm());signature.initSign(priKey);signature.update(data);returnencryptBASE64(signature.sign());}/** * 校验数字签名 * * param data * 加密数据 * param publicKey * 公钥 * param sign * 数字签名 * * return 校验成功返回true 失败返回false * throws Exception * */ public static boolean verify(byte[]data, String publicKey, String sign)throws Exception{// 解密由base64编码的公钥 byte[]keyBytesdecryptBASE64(publicKey);// 构造X509EncodedKeySpec对象 X509EncodedKeySpec keySpecnew X509EncodedKeySpec(keyBytes);// ALGORITHM 指定的加密算法 KeyFactory keyFactoryKeyFactory.getInstance(ALGORITHM);// 取公钥匙对象 PublicKey pubKeykeyFactory.generatePublic(keySpec);Signature signatureSignature.getInstance(keyFactory.getAlgorithm());signature.initVerify(pubKey);signature.update(data);// 验证签名是否正常returnsignature.verify(decryptBASE64(sign));}/** * 生成密钥 * * param seed * 种子 * return 密钥对象 * throws Exception */ public static MapString, ObjectinitKey(String seed)throws Exception{KeyPairGenerator keygenKeyPairGenerator.getInstance(ALGORITHM);// 初始化随机产生器 SecureRandom secureRandomnew SecureRandom();secureRandom.setSeed(seed.getBytes());keygen.initialize(KEY_SIZE, secureRandom);KeyPair keyskeygen.genKeyPair();DSAPublicKey publicKey(DSAPublicKey)keys.getPublic();DSAPrivateKey privateKey(DSAPrivateKey)keys.getPrivate();MapString, Objectmapnew HashMapString, Object(2);map.put(PUBLIC_KEY, publicKey);map.put(PRIVATE_KEY, privateKey);returnmap;}/** * 默认生成密钥 * * return 密钥对象 * throws Exception */ public static MapString, ObjectinitKey()throws Exception{returninitKey(DEFAULT_SEED);}/** * 取得私钥 * * param keyMap * return * throws Exception */ public static String getPrivateKey(MapString, ObjectkeyMap)throws Exception{Key key(Key)keyMap.get(PRIVATE_KEY);returnencryptBASE64(key.getEncoded());}/** * 取得公钥 * * param keyMap * return * throws Exception */ public static String getPublicKey(MapString, ObjectkeyMap)throws Exception{Key key(Key)keyMap.get(PUBLIC_KEY);returnencryptBASE64(key.getEncoded());}}ECC算法4.1 简介椭圆加密算法ECC是一种公钥加密算法最初由 Koblitz 和 Miller 两人于1985年提出其数学基础是利用椭圆曲线上的有理点构成 Abel 加法群上椭圆离散对数的计算困难性。公钥密码体制根据其所依据的难题一般分为三类大整数分解问题类、离散对数问题类、椭圆曲线类。有时也把椭圆曲线类归为离散对数类。ECC 的主要优势是在某些情况下它比其他的方法使用更小的密钥 (比如 RSA)提供相当的或更高等级的安全。ECC 的另一个优势是可以定义群之间的双线性映射基于 Weil 对或是 Tate 对双线性映射已经在密码学中发现了大量的应用例如基于身份的加密。不过一个缺点是加密和解密操作的实现比其他机制花费的时间长。ECC 被广泛认为是在给定密钥长度的情况下最强大的非对称算法因此在对带宽要求十分紧的连接中会十分有用。比特币钱包公钥的生成使用了椭圆曲线算法通过椭圆曲线乘法可以从私钥计算得到公钥 这是不可逆转的过程。4.2 优势(1) 安全性高有研究表示160位的椭圆密钥与1024位的 RSA 密钥安全性相同。(2) 处理速度快在私钥的加密解密速度上ECC 算法比 RSA、DSA 速度更快存储空间占用小带宽要求低。4.3 例子https://github.com/esxgx/easy-eccJava 中 Chipher、Signature、KeyPairGenerator、KeyAgreement、SecretKey 均不支持 ECC 算法。DH算法5.1 简介DH全称为Diffie-Hellman它是一种确保共享 KEY 安全穿越不安全网络的方法也就是常说的密钥一致协议。由公开密钥密码体制的奠基人 Diffie 和 Hellman 所提出的一种思想。简单的说就是允许两名用户在公开媒体上交换信息以生成一致的、可以共享的密钥。也就是由甲方产出一对密钥 (公钥、私钥)乙方依照甲方公钥产生乙方密钥对 (公钥、私钥)。以此为基线作为数据传输保密基础同时双方使用同一种对称加密算法构建本地密钥 (SecretKey) 对数据加密。这样在互通了本地密钥 (SecretKey) 算法后甲乙双方公开自己的公钥使用对方的公钥和刚才产生的私钥加密数据同时可以使用对方的公钥和自己的私钥对数据解密。不单单是甲乙双方两方可以扩展为多方共享数据通讯这样就完成了网络交互数据的安全通讯。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2422175.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!