RSA详解 ----- Android中常用的非对称加密算法

1.android 端加密方式

  • 非对称加密 (RSA)
  • 对称加密 (DES,AES,3DES)
  • MD5加密
  • BASE64编码

ps:这篇主要介绍android rsa加密

2.Rsa加密原理

1.随机选择两个大质数p和q,p不等于q,计算N=pq;

2.选择一个大于1小于N的自然数e,e必须与(p-1)(q-1)互素。

3.用公式计算出d:d×e = 1 (mod (p-1)(q-1)) 。

4.销毁p和q。

最终得到的N和e就是“公钥”,d就是“私钥”,发送方使用N去加密数据,接收方只有使用d才能解开数据内容。

3.Rsa相比对称加密算法优缺点

优点:

  • 对称加密比对称加密算法更安全

缺点:

  • 加密速度更慢,适用于加密少量数据

4.示例 (公钥加密,私钥解密)

通过公钥字符串 获取PublicKey对象

            byte[] buffer = Base64Utils.decode(publicKeyStr);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
            RSAPublicKey publicKey =  (RSAPublicKey) RSAPublicKey.generatePublic(keySpec);
复制代码

使用publickey加密数据

            Cipher cipher = Cipher.getInstance("转换");
            // 编码前设定编码方式及密钥
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            // 传入编码数据并返回编码结果
            byte[] encrptData = cipher.doFinal(data);
复制代码

几个关键参数介绍:

1.转换 是一个字符串,它描述为产生某种输出而在给定的输入上执行的操作(或一组操作); 形式可以是 算法/模式/填充算法; 常见的模式如下:

RSA (如果你的明文不够128字节加密的时候会在你的明文前面,前向的填充零。解密后的明文也会包括前面填充的零,这是服务器需要注意把解密后的字段前向填充的零去掉,才是真正之前加密的明文。)

RSA/ECB/PKCS1Padding (加密的时候会在你的明文中随机填充一些数据,所以会导致对同样的明文每次加密后的结果都不一样)

RSA/None/PKCS1Padding

第一个 RSA 等价于 RSA/None/NoPadding .使用此模式加密后 同一个明文、同一个公钥每次生成同一个密文.攻击者能够据此识别到同一个信息都是何时被发送。 所以一般使用第二个 RSA/ECB/PKCS1Padding .

2.编码方式设定

cipher.init(MODE, publicKey);

常见编码方式 (MODE):

ENCRYPT_MODE: Cipher 初始化为加密模式的常量 (常用)

DECRYPT_MODE: Cipher 初始化为解密模式的常量 (常用)

WRAP_MODE :Cipher 初始化为密钥包装模式的常量

UNWRAP_MODE :Cipher 初始化为密钥解包模式的常量

PUBLIC_KEY :解包的密钥为“公钥”的常量

PRIVATE_KEY : 解包的密钥为“私钥”的常量

SECRET_KEY :解包的密钥为“秘密密钥”的常量

5.开发过程中容易遇到的坑

1.客户端需要与后端确认好使用同一转换模式 做到一一对应. 如果后端(java使用 RSA),则前端 需要使用(RSA/ECB/PKCS1Padding) 而不是 RSA.

2.前端请求下来的公钥字符串如果 包含 "-----BEGIN PUBLIC KEY-----" 和 "-----END PUBLIC KEY-----",需要将其切掉,如果直接使用 会报 InvalidKeySpecException .


转载自:https://juejin.im/post/5be103685188255e9b617dd7
 

RSA封装类 ,完整的RSA加密和解密 public class RSAUtilEncrypt { public static final String KEY_ALGORTHM = "RSA";// public static final String KEY_ALGORTHM_RSA_ECB_PKCS1PADDING = "RSA/ECB/PKCS1Padding"; public static String RSA_PUBLIC_KEY = "rsa_public_key"; public static String RSA_PRIVATE_KEY = "rsa_private_key"; private int KeySize = 1024; private Map keyMap; private static String RSA = "RSA"; private static PublicKey publickey; public RSAUtilEncrypt(int KeySize,String publickey) { this.KeySize = KeySize; try { this.publickey=generatePublicKeyByString(publickey); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private RSAPublicKey generatePublicKeyByString(String publicKeyStr) throws Exception { try { BASE64Decoder base64Decoder = new BASE64Decoder(); byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return (RSAPublicKey) keyFactory.generatePublic(keySpec); } catch (NoSuchAlgorithmException e) { throw new Exception("No Algorthm,Checked by cemung!"); } catch (InvalidKeySpecException e) { throw new Exception("InvalidKeySpec!"); } catch (IOException e) { throw new Exception("Io exception!"); } catch (NullPointerException e) { throw new Exception("Illegle pointer reference!"); } } // Encypt public byte[] RSAEncrypt(byte[] data, RSAPublicKey publickey) throws Exception { Cipher cipher = Cipher.getInstance(KEY_ALGORTHM_RSA_ECB_PKCS1PADDING); cipher.init(Cipher.ENCRYPT_MODE, this.publickey); byte[] cipherbytes = cipher.doFinal(data); return cipherbytes; } // Encypt public byte[] RSAEncrypt(byte[] data) throws Exception { Cipher cipher = Cipher.getInstance(KEY_ALGORTHM_RSA_ECB_PKCS1PADDING); cipher.init(Cipher.ENCRYPT_MODE, this.publickey); byte[] cipherbytes = cipher.doFinal(data); return cipherbytes; } // Get Public key with format byte[] public byte[] getPublicKeyByte() { RSAPublicKey pubkey = (RSAPublicKey) keyMap.get(RSA_PUBLIC_KEY); return pubkey.getEncoded(); } public static byte[] decryptBASE64(String key) throws Exception { return (new BASE64Decoder()).decodeBuffer(key); } public static String encryptBASE64(byte[] key) throws Exception { return (new BASE64Encoder()).encodeBuffer(key); } public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception { byte[] keyBytes = decryptBASE64(key); PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec( keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(data); } public static byte[] encryptByPublicKey(byte[] data, String key) throws Exception { byte[] keyBytes = decryptBASE64(key); X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data); } public static byte[] decryptByPublicKey(byte[] data, String key) throws Exception { byte[] keyBytes = decryptBASE64(key); X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM); Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(data); } 使用方法 private RSAUtilEncrypt rsa = new RSAUtilEncrypt(1024, publikey); /* * 给信息加密,获取密文 */ public String getCiphertext(String str_encrode) { try { byte[] estr = rsa.RSAEncrypt(str_encrode.getBytes()); // 密文 String ciphertext = Base64.encodeToString(estr, Base64.DEFAULT); return ciphertext; } catch (Exception e) { e.printStackTrace(); } return null; } 有疑问的留言
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值