[Adnroid] RSA加解密篇

简介

RSA算法属于非对称加密算法,非对称加密算法需要两个秘钥:公开密钥(publickey)和私有秘钥(privatekey).公开密钥和私有秘钥是一对,如果公开密钥对数据进行加密,只有用对应的私有秘钥才能解密;如果私有秘钥对数据进行加密那么只有用对应的公开密钥才能解密.因为加密解密使用的是两个不同的秘钥,所以这种算法叫做非对称加密算法.简单的说就是公钥加密私钥解密,私钥加密公钥解密

获取公私钥

通过KeyPairGenerator.getInstance("RSA");来获取RSA的公钥与私钥,1024长度的密钥最大解密密文大小为128,最大加密密文大小为127。2048长度的密钥最大解密密文大小为256,最大加密密文大小为255。本文使用2048长度的key,密文过大是会使用分段加解密。

开发中通常会使用公钥加密,使用私钥解密。所以通常会有2对公私钥来使前后端相互通信。

所以本文只说公钥加密,使用私钥解密方法

/** 生成密钥对,即公钥和私钥。key长度是512-2048,一般为1024 本文使用2048长度的key*/
    public static KeyPair generateRSAKeyPair(int keyLength) throws NoSuchAlgorithmException {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(keyLength);
        return kpg.genKeyPair();
    }

    /** 获取公钥*/
    public static byte[] getPublicKey(KeyPair keyPair) {
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        return rsaPublicKey.getEncoded();
    }

    /** 获取私钥*/
    public static byte[] getPrivateKey(KeyPair keyPair) {
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
        return rsaPrivateKey.getEncoded();
    }

使用公钥加密

/**
     * 使用公钥加密
     * @param content 需要加密的密文(String类型)
     * @param publicKeyString 公钥(String类型)
     * @return base64数据
     * @throws Exception
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    public static String encryptByPublicKey(String content, String publicKeyString) throws Exception {

        byte[] publicKey = Base64.getDecoder().decode(publicKeyString.getBytes());
        // 得到公钥对象
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey pubKey = keyFactory.generatePublic(keySpec);
        // 加密数据
        Cipher cp = Cipher.getInstance(TRANSFORMATION);
        cp.init(Cipher.ENCRYPT_MODE, pubKey);
        byte[] byteArray =  cp.doFinal(content.getBytes());

        return byteArray != null?Base64.getEncoder().encodeToString(byteArray):null;
    }
使用私钥解密
/**
 * 使用私钥解密
 * @param content content 需要加密的密文
 * @param privateKeyString  私钥
 * @return String数据所以需要fastjson转object
 * @throws Exception
 */
@RequiresApi(api = Build.VERSION_CODES.O)
public static String decryptByPrivateKey(String content, String privateKeyString) throws Exception {
    byte[] privateKey = Base64.getDecoder().decode(privateKeyString.getBytes());
    byte[] encrypt =  Base64Utils.decodeToBytes(content);
    // 得到私钥对象
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    PrivateKey keyPrivate = kf.generatePrivate(keySpec);
    // 解密数据
    Cipher cp = Cipher.getInstance(TRANSFORMATION);
    cp.init(Cipher.DECRYPT_MODE, keyPrivate);
    byte[] byteArray = cp.doFinal(encrypt);

    return byteArray!=null?new String(byteArray):null;
}
使用公钥分段加密

1024长度的密钥最大解密密文大小为128,最大加密密文大小为127;2048长度的密钥最大解密密文大小为256,最大加密密文大小为255(本文使用2048长度的key)。

/**
 * RSA最大加密明文大小
 */
private static final int MAX_ENCRYPT_BLOCK = 255;
/**
 * RSA最大解密密文大小
 */
private static final int MAX_DECRYPT_BLOCK = 256;

/**
 * 使用公钥分段加密
 * @param content 需要加密的密文(String类型)
 * @param publicKeyString 公钥(String类型)
 * @return base64数据
 */
@RequiresApi(api = Build.VERSION_CODES.O)
public static String encryptByPublicKeySection(String content , String publicKeyString) {

    byte[] publicKey = Base64.getDecoder().decode(publicKeyString.getBytes());
    // 加密
    String str = "";
    try {
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
        KeyFactory fac = KeyFactory.getInstance("RSA");
        RSAPublicKey rsaPubKey = (RSAPublicKey) fac.generatePublic(keySpec);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, rsaPubKey);
        int inputLen = content.getBytes().length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        while (inputLen - offSet > 0) {
            //MAX_ENCRYPT_BLOCK 117
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(content.getBytes(), offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(content.getBytes(), offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();

        str = Base64.getEncoder().encodeToString(encryptedData);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return str;
}
使用私钥分段解密

同上

**
 * RSA最大加密明文大小
 */
private static final int MAX_ENCRYPT_BLOCK = 255;
/**
 * RSA最大解密密文大小
 */
private static final int MAX_DECRYPT_BLOCK = 256;

/**
 * 使用私钥分段解密
 * @param data 已经加密的密文(通常为base64类型)
 * @param privateKeyString 私钥(String类型)
 * @return
 */
@RequiresApi(api = Build.VERSION_CODES.O)
public static String decryptByPrivateKeySection(String data , String privateKeyString) {
    byte[] privateKey = Base64.getDecoder().decode(privateKeyString.getBytes());
    // 加密
    String str = "";
    try {
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
        KeyFactory fac = KeyFactory.getInstance("RSA");
        RSAPrivateKey privateKey = (RSAPrivateKey) fac.generatePrivate(keySpec);
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        byte[] dataBytes = Base64Utils.decodeToBytes(data);
        int inputLen = dataBytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 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);
            i++;
            offset = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        // 解密后的内容
        str = new String(decryptedData);

    } catch (Exception e) {
        e.printStackTrace();
    }
    return str;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值