RSA 分组加密算法,非对称加密算法
参考RSA - 原理、特点(加解密及签名验签)及公钥和私钥的生成
基于–大数N难分解 e*d≡1mod(r)--->e*d≡1mod(φ(N))
公钥私钥获取 随意选择两个大的质数p和q,p不等于q,计算N=pq。 根据欧拉函数,求得r=φ(N)=φ(p)φ(q)=(p−1)(q−1) 选择一个小于r的整数e,使e与r互质。并求得e关于r的模反元素,命名为d(求d令ed≡1(modr))。(模反元素存在,当且仅当e与r互质;将p和q的记录销毁。 (N,e)是公钥,(N,d)是私钥。公钥发送给所有的通信对象(对服务器来说就是所有的客户端),私钥则必须保管好,防止泄露。
数学原理
欧拉函数:求小于N的正整数中与N互质的数的数目。φ(N) :φ(11)=10; φ(4)=2[1,3]; φ(8)=4[1,3,5,7]
欧拉定理证明当a,n为两个互素的正整数时,则有a^φ(n)≡1(modn),其中 φ(n)为欧拉函数(小于等于n且与n互素的正整数个数)。
加密过程 明文:m 公钥(N,e) 密文:c≡m^e(mod N)
解密过程 密文:c 私钥(N,d) 明文: c^d(mod N)
1 2 3 4 5 6 7 8 9 10 11 12 13 c^d(mod N)≡ m^de(mod N) 由于ed≡1(modr) --> ed≡1(mod φ(N)) c^d(mod N)≡ m^de(mod N) ≡ m^ (Kφ(N)+1) (mod N) ≡m* (m^ φ(N))^K (mod N) //K 为倍系数 倍数 N=p*q (p,q为两不相同大质数),m与N互质 m^φ(N) ≡ 1 mod N c^d(mod N)≡ m^de(mod N) ≡ m^ (Kφ(N)+1) (mod N) ≡m* (m^ φ(N))^K (mod N) ≡ m *1^K (mod N)≡m (mod N)
使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 方式一: BigInteger rs = new BigInteger (String.format("%x" , new BigInteger (1 , text.getBytes())), 16 ) .modPow(new BigInteger (pubKey, 16 ), new BigInteger (modulus, 16 )); String result = rs.toString(16 );方式二: RSAPublicKeySpec keySpec = new RSAPublicKeySpec (modulus, pubkey);KeyFactory keyFactory = KeyFactory.getInstance("RSA" );PublicKey publicKey = keyFactory.generatePublic(keySpec);Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding" );cipher.init(Cipher.ENCRYPT_MODE, publicKey); randomStr = new StringBuilder (randomStr).reverse().toString(); byte [] data = randomStr.getBytes("utf-8" );int inputLen = data.length;ByteArrayOutputStream out = new ByteArrayOutputStream ();int offSet = 0 ;byte [] cache;int i = 0 ;while (inputLen - offSet > 0 ) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0 , cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte [] encryptedData = out.toByteArray();out.close(); String result = byte2HexString(encryptedData);
DSA(Digital Signature Algorithm) DSA是基于整数有限域离散对数难题的,其安全性与RSA相比差不多。DSA的一个重要特点是两个素数公开,这样,当使用别人的p和q时,即使不知道私钥,你也能确认它们是否是随机产生的,还是作了手脚。RSA算法却做不到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 算法中应用了下述参数: p:L bits长的素数。L是64的倍数,范围是512到1024; q:p - 1的160bits的素因子; g:g = h^((p-1)/q) mod p,h满足h < p - 1, h^((p-1)/q) mod p > 1; x:x < q,x为私钥 ; y:y = g^x mod p ,( p, q, g, y )为公钥; H( x ):One-Way Hash函数。DSS(FIPS186-4)中选用SHA-1或者SHA-2( Secure Hash Algorithm系列中的2个较新版本,其中SHA-2有4个,SHA-224,SHA-256,SHA-384,SHA-512,最原始的SHA已经不再被使用)。 p, q, g可由一组用户共享,但在实际应用中,使用公共模数可能会带来一定的威胁。签名及验证协议如下: 1. P产生随机数k,k < q; 2. P计算 r = ( g^k mod p ) mod q s = ( k^(-1) (H(m) + xr)) mod q 签名结果是( m, r, s )。 3. 验证时计算 w = s^(-1)mod q u1 = ( H( m ) * w ) mod q u2 = ( r * w ) mod q v = (( g^u1 * y^u2 ) mod p ) mod q 若v = r,则认为签名有效。
使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 import org.apache.commons.codec.binary.Base64;public class DSACoder { public static final String KEY_ALGORITHM="DSA" ; public static final String SIGNATURE_ALGORITHM="SHA1withDSA" ; private static final int KEY_SIZE=1024 ; private static final String PUBLIC_KEY="DSAPublicKey" ; private static final String PRIVATE_KEY="DSAPrivateKey" ; public static Map<String,Object> initKey () throws Exception{ KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance(KEY_ALGORITHM); keyPairGenerator.initialize(KEY_SIZE,new SecureRandom ()); KeyPair keyPair=keyPairGenerator.generateKeyPair(); DSAPublicKey publicKey=(DSAPublicKey) keyPair.getPublic(); DSAPrivateKey privateKey=(DSAPrivateKey) keyPair.getPrivate(); Map<String,Object> keyMap=new HashMap <String,Object>(); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } public static byte [] sign(byte [] data,byte [] privateKey) throws Exception{ PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec (privateKey); KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey priKey=keyFactory.generatePrivate(pkcs8KeySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(priKey); signature.update(data); return signature.sign(); } public static boolean verify (byte [] data,byte [] publicKey,byte [] sign) throws Exception{ KeyFactory keyFactory=KeyFactory.getInstance(KEY_ALGORITHM); X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec (publicKey); PublicKey pubKey=keyFactory.generatePublic(x509KeySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(pubKey); signature.update(data); return signature.verify(sign); } public static byte [] getPrivateKey(Map<String,Object> keyMap){ Key key=(Key)keyMap.get(PRIVATE_KEY); return key.getEncoded(); } public static byte [] getPublicKey(Map<String,Object> keyMap) throws Exception{ Key key=(Key) keyMap.get(PUBLIC_KEY); return key.getEncoded(); } public static void main (String[] args) throws Exception { Map<String,Object> keyMap=DSACoder.initKey(); byte [] publicKey=DSACoder.getPublicKey(keyMap); byte [] privateKey=DSACoder.getPrivateKey(keyMap); System.out.println("公钥:/n" +Base64.encodeBase64String(publicKey)); System.out.println("私钥:/n" +Base64.encodeBase64String(privateKey)); System.out.println("================密钥对构造完毕,甲方将公钥公布给乙方,开始进行加密数据的传输=============" ); String str="DSA数字签名算法" ; System.out.println("原文:" +str); byte [] sign=DSACoder.sign(str.getBytes(), privateKey); System.out.println("产生签名:" +Base64.encodeBase64String(sign)); boolean status=DSACoder.verify(str.getBytes(), publicKey, sign); System.out.println("状态:" +status+"/n/n" ); } } 控制台输出: 公钥: MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZp RV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fn xqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuE C/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJ FnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImo g9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAdLUOPbXqOQi4MFUm5tgBs2zQO20P7P1iPCC9 pslWvixp13NX9dTwdddkwqQtwKAfm/Ao2Gqe7VGq48kTIPr0wz01LKlCLbbw6VLikuFcgVNN+sVx mwVTm54aFpiOaenS575Qtyek3zjVV+eMtRNKn91rMMWpsP6pucqku6xO5uY= 私钥: MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2 USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4 O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC ouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCB gLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhR kImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFgIUQhtJHLosUo0sxPKmCxC8NFVjD9c= ================密钥对构造完毕,甲方将公钥公布给乙方,开始进行加密数据的传输============= 原文:DSA数字签名算法 产生签名:MCwCFAsJPC7xUfrvGYXtsxiWcS6GHAe1AhRnZLZ1CJe8I41vaScvJ7UZ8yk0oA== 状态:true
总结
DSA的公钥长度略长于私钥,这个和RSA有较大差别。可以通过两个算法的控制台输出公钥私钥长度比对
DSA算法的签名长度与密钥长度无关。可能和待签名数据有联系…