当前位置: 首页 > 科技观察

非对称加密的RSA加密是怎样的

时间:2023-03-22 00:22:28 科技观察

前几天阿芬刚说了这个MD5加密的前世今生,因为MD5确实用的人不多,就不一一继续赘述了一。阿芬今天要给大家分享的是一种非对称加密,也就是RSA加密算法。对称加密和非对称加密在说RSA之前,我们不得不先说说什么是对称加密,什么是非对称加密?对称加密是指加密和解密使用相同的密钥,所以称为对称加密。对称加密只有一个密钥,作为私钥。非对称加密是指加密和解密使用不同的秘钥,一个作为公钥,一个作为私钥。用公钥加密的信息只能用私钥解密。那么对称加密和非对称加密有什么区别呢?对称加密中加密和解密使用同一个秘钥;非对称加密使用两个密钥,一般是公钥用于加密,私钥用于解密。对称加密和解密比较快,非对称加密和解密时间长,速度也比较慢。对称加密的安全性比较低,非对称加密的安全性高。今天我们说的是非对称加密中的RSA加密。什么是RSA加密?RSA加密是一种非对称加密。无需直接传递密钥即可完成解密。这样既可以保证信息的安全性,又可以避免因直接传递密钥而被破解的风险。它是通过一对密钥进行加密和解密的过程,分别称为公钥和私钥。通常情况下,私钥个人保管,公钥是公开的(可能多人同时持有)。虽然私钥是根据公钥确定的,但是我们没有办法从公钥推导出私钥。为增加安全强度,RSA密钥必须至少有500位长。这使得加密计算密集。为了减少计算量,在传输信息时,往往采用传统加密方式和公钥加密方式相结合的方式,即用改进的DES或IDEA会话密钥对信息进行加密,然后将会话密钥和信息使用RSA密钥摘要加密。对方收到信息后,可以用不同的密钥解密,查看信息摘要。RSA加密过程RSA加密过程其实并不复杂。(1)A生成一对密钥(公钥和私钥),A公钥自己保管。公钥是公开的,任何人都可以获得。(2)A将自己的公钥传给B,B用A的公钥加密消息。(3)A收到B的加密消息,用A自己的私钥解密消息。在这个过程中,只有2个交付过程。第一次是A把公钥传给B,第二次是B把密文传给A,即使都被别人截获也没有危险,因为只有A的私钥才能解密消息,防止消息内容泄露。但是大家有没有想过,如果我们的消息被拦截了,虽然还没有解密,但是如果我们的公钥被拦截了,然后把这个fakecommand加密再传给A,岂不是很爽?数据不再安全了吗?不,RSA还有签名的过程。签名过程如下:(1)A生成一对密钥(公钥和私钥),私钥不公开,A自己保管。公钥是公开的,任何人都可以获得。(2)A用自己的私钥对消息进行签名,形成签名,将签名后的消息连同消息本身传递给B。(3)B收到消息后,获取A的公钥来验证签名。如果签名内容与消息本身一致,则证明消息是A回复的。但是问题又来了。截获的消息虽然不能被篡改,但是通过公钥签名验证可以得到消息的内容,不能防止泄密。那么应该如何使用呢?其实这不是很容易理解。我们能不能这样设计:A和B有自己的公钥和私钥。当A要向B发送消息时,它首先使用B的公钥对消息进行加密,然后用A的私钥对加密后的消息进行签名,这样就不会泄露和篡改,保证消息的安全性。那么Java代码是如何实现RSA的呢?代码如下:。安全。签名;导入java.security.spec.PKCS8EncodedKeySpec;导入java.security.spec.X509EncodedKeySpec;导入javax.crypto.Cipher;导入org.apache.commons.codec.binary.Base64;公共类TestRSA{/***RSAmax加密明文大小*/privatestaticfinalintMAX_ENCRYPT_BLOCK=117;/***RSA最大解密密文大小*/privatestaticfinalintMAX_DECRYPT_BLOCK=128;/***获取密钥对**@return密钥对*/publicstaticKeyPairgetKeyPair()throwsException{KeyPairGeneratorgenerator=KeyPairGenerator.getInstance("RSA");生成器.初始化(1024);返回generator.generateKeyPair();}/***获取私钥**@paramprivateKey私钥字符串*@return*/publiccstaticPrivateKeygetPrivateKey(StringprivateKey)抛出异常{KeyFactorykeyFactory=KeyFactory.getInstance("RSA");byte[]decodedKey=Base64.decodeBase64(privateKey.getBytes());PKCS8EncodedKeySpeckeySpec=newPKCS8EncodedKeySpec(decodedKey);返回keyFactory.generatePrivate(keySpec);}/***获取公钥**@parampublicKey公钥字符串*@return*/publicstaticPublicKeygetPublicKey(StringpublicKey)throwsException{KeyFactorykeyFactory=KeyFactory.getInstance("RSA");byte[]decodedKey=Base64.decodeBase64(publicKey.getBytes());X509EncodedKeySpeckeySpec=newX509EncodedKeySpec(decodedKey);返回keyFactory.generatePublic(keySpec);}/***RSA加密**@paramdata待加密数据*@parampublicKey公钥*@return*/publicstaticStringencrypt(Stringdata,PublicKeypublicKey)throwsException{Ciphercipher=Cipher.getI实例(“RSA”);cipher.init(Cipher.ENCRYPT_MODE,publicKey);intinputLen=data.getBytes().length;ByteArrayOutputStreamout=newByteArrayOutputStream();int偏移量=0;字节[]缓存;诠释我=0;//加密数据段while(inputLen-offset>0){if(inputLen-offset>MAX_ENCRYPT_BLOCK){cache=cipher.doFinal(data.getBytes(),offset,MAX_ENCRYPT_BLOCK);}else{cache=cipher.doFinal(data.getBytes(),offset,inputLen-offset);}out.write(cache,0,cache.length);我++;offset=i*MAX_ENCRYPT_BLOCK;}byte[]encryptedData=out.toByteArray();关闭();//获取加密后的内容并使用base64编码,将其转换为基于UTF-8的字符串//加密后的字符串returnnewString(Base64.encodeBase64String(encryptedData));}/***RSA解密**@paramdata待解密数据*@paramprivateKey私钥*@return*/publicstaticStringdecrypt(Stringdata,PrivateKeyprivateKey)throwsException{Ciphercipher=Cipher.getInstance("RSA");}cipher.init(Cipher.DECRYPT_MODE,privateKey);byte[]dataBytes=Base64.decodeBase64(数据);intinputLen=dataBytes.length;ByteArrayOutputStreamout=newByteArrayOutputStream();int偏移量=0;字节[]缓存;诠释我=0;//对数据分段解密while(inputLen-offset>0){if(inputLen-offset>MAX_DECRYPT_BLOCK){cache=cipher.doFinal(dataBytes,offset,MAX_DECRYPT_BLOCK);}else{cache=cipher.doFinal(dataBytes,offset,inputLen-offset);}out.write(cache,0,cache.length);我++;offset=i*MAX_DECRYPT_BLOCK;}byte[]decryptedData=out.toByteArray();关闭();//解密后的内容returnnewString(decryptedData,"UTF-8");}/***signature**@paramdata待签名数据*@paramprivateKeyprivatekey*@returnsignature*/publicstaticStringsign(Stringdata,PrivateKeyprivateKey)throwsException{byte[]keyBytes=privateKey.getEncoded();PKCS8EncodedKeySpeckeySpec=newPKCS8EncodedKeySpec(keyBytes);KeyFactorykeyFactory=KeyFactory.getInstance("RSA");私钥key=keyFactory.generatePrivate(keySpec);签名signature=Signature.getInstance(RSA");signature.initSign(key);signature.update(data.getBytes());returnnewString(Base64.encodeBase64(signature.sign()));}/***签名验证**@paramsrcDataoriginalString*@parampublicKeypublickey*@paramsignsignature*@return签名验证是否通过*/publicstaticbooleanverify(StringsrcData,PublicKeypublicKey,Stringsign)throwsException{byte[]keyBytes=publicKey.getEncoded();X509EncodedKeySpeckeySpec=newX509EncodedKeySpec(keyBytes);KeyFactorykeyFactory=KeyFactory.getInstance("RSA");PublicKeykey=keyFactory.generatePublic(keySpec);签名signature=Signature.getInstance("MD5withRSA");signature.initVerify(密钥);signature.update(srcData.getBytes());返回signature.verify(Base64.decodeBase64(sign.getBytes()));}publicstaticvoidmain(String[]args){try{//生成密码对KeyPairkeyPair=getKeyPair();StringprivateKey=newString(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));StringpublicKey=newString(Base64.encodeBase64(keyPair.getPublic().getEncoded()));System.out.println("私钥:"+privateKey);System.out.println("公钥:"+publicKey);//RSA加密Stringdata="待加密的文字内容";字符串加密数据=加密(数据,getPublicKey(公钥));系统.out.println("加密内容:"+encryptData);//RSA解密StringdecryptData=decrypt(encryptData,getPrivateKey(privateKey));System.out.println("解密后的内容:"+decryptData);//RSA签名Stringsign=sign(data,getPrivateKey(privateKey));//RSA签名验证booleanresult=verify(data,getPublicKey(publicKey),sign);System.out.print("签名验证结果:"+result);}catch(Exceptione){e.printStackTrace();System.out.print("加解密异常");}}}同样,当我们看到RSA的Java实现时,我们可以看到它的缺点。先定义最大加密明文大小和最大解密密文大小,那么这个117是怎么来的呢?Java默认的RSA加密实现不允许明文长度超过密钥长度-11(单位是bytes,即byte)。即如果我们定义密钥(可以通过java.security.KeyPairGenerator.initialize(intkeysize)定义密钥长度)长度为1024(单位为bit,即bit),则生成的密钥长度为1024位/8位/字节=128字节,那么我们需要加密的明文长度不能超过128字节-11字节=117字节。也就是说,我们最多可以加密117字节长的明文,否则就会出现问题(javax.crypto.IllegalBlockSizeException:Datamustnotbelongerthan53bytesexception)。那么在使用RSA时应该注意什么呢?1、加密系统不应该有解密的功能,否则RSA可能不适合,因为即使黑客攻破了加密系统,得到的也只是一堆无法破解的密文数据。2、生成的密文长度与明文长度无关,但明文长度不能超过密钥长度。无论明文长度如何,RSA生成的密文长度始终是固定的。但明文长度不能超过密钥长度。也就是上面阿芬说的117个字节,不然只能等异常发生了。你知道RSA吗?