Android中RSA公钥加密后Java服务端私钥无法解密问题解决

工作中经常需要Android客户端使用RSA公钥加密敏感数据,服务端再使用配套的RSA私钥解密数据,最近碰到一个问题,使用RSA加密后服务端无法解密,查阅相关资料后,发现是这个问题:

RSA操作的填充方式不对。

android系统的RSA实现是"RSA/None/NoPadding",

而标准JDK实现是"RSA/None/PKCS1Padding" ,

那解决方法是加解密填充方法改成一致呗。

比如填充方式统一改成:RSA/ECB/PKCS1Padding

另外注意服务端用的是java.util.Base64

客户端用的是android.util.Base64

服务端RsaUtils.java

package com.figo.study2024.utils;

import org.springframework.beans.factory.annotation.Value;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RsaUtils {
    /**
     * 加密算法.
     */
    public static final String KEY_ALGORITHM_KEY = "RSA";

    public static final String KEY_ALGORITHM = "RSA/ECB/PKCS1Padding";


    /**
     * 私钥解密.
     *
     * @param privateKeyString 私钥
     * @param text             待解密的文本
     * @return 解密后的文本
     */
    public static String decryptByPrivateKey(String privateKeyString, String text) {
        try {
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyString));
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_KEY);
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] result = cipher.doFinal(Base64.getDecoder().decode(text));
            return new String(result);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 公钥加密.
     *
     * @param publicKeyString 公钥
     * @param text            待加密的文本
     * @return 加密后的文本
     */
    public static String encryptByPublicKey(String publicKeyString, String text) {
        try {
            X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyString));
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_KEY);
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] result = cipher.doFinal(text.getBytes());
            return new String(Base64.getEncoder().encode(result));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 构建RSA密钥对.
     *
     * @return 生成后的公私钥信息
     */
    public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM_KEY);
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
        String publicKeyString = new String(Base64.getEncoder().encode(rsaPublicKey.getEncoded()));
        String privateKeyString = new String(Base64.getEncoder().encode(rsaPrivateKey.getEncoded()));
        return new RsaKeyPair(publicKeyString, privateKeyString);
    }

    /**
     * RSA密钥对对象.
     */

    public static class RsaKeyPair {
        public RsaKeyPair(String publicKey, String privateKey) {
            this.publicKey = publicKey;
            this.privateKey = privateKey;
        }

        /**
         * 公钥.
         */
        private String publicKey;

        /**
         * 私钥.
         */
        private String privateKey;

        public String getPublicKey() {
            return publicKey;
        }

        public void setPublicKey(String publicKey) {
            this.publicKey = publicKey;
        }

        public String getPrivateKey() {
            return privateKey;
        }

        public void setPrivateKey(String privateKey) {
            this.privateKey = privateKey;
        }
    }




    public static void main(String[] args){
        // 生成公私钥对
        RsaKeyPair keyPair = null;
        try {
            keyPair = generateKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        System.out.println("keyPair.getPublicKey() = " + keyPair.getPublicKey());
        System.out.println("keyPair.getPrivateKey() = " + keyPair.getPrivateKey());
        String text = "figo";
        System.out.println("原明文 = " + text);
        // 公钥加密
        String encryptStr = RsaUtils.encryptByPublicKey(keyPair.getPublicKey(), text);
        // 私钥解密
        String plain = RsaUtils.decryptByPrivateKey(keyPair.getPrivateKey(), encryptStr);
//        String publicKey="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA42XXuzyZROCrRHVlHiDotl90KG0gSrrZzPuMrl608Pj2MU9sZAGpsMcbJ627Uv6vrzGigeC0qCdv7cRTW2CuF6jQhIYjo6bmNtVK+ysvWl0KEacAik2gvL4g/686J/7FBnv4xZywQ1+A2Bevh4ZaEVqE09zC0TJM8DU5mfalOGnA13m7QS9bvjPB27Tzl2TA1SYE7+FfI1mTycZJmvhEv6+jiWxS/08OASsEPzdB/j5vn4Y/WvsgYw+3ZoahfvdpMCIhlpW6Wsf9dhGcPtYqfGpn6ldh6b+nJQ0NGpS6c1ov16RYGwZFOWQfpbTVKF0enVMumXwN+OWgr0NQxP7nBQIDAQAB";
//        String privateKey="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDjZde7PJlE4KtEdWUeIOi2X3QobSBKutnM+4yuXrTw+PYxT2xkAamwxxsnrbtS/q+vMaKB4LSoJ2/txFNbYK4XqNCEhiOjpuY21Ur7Ky9aXQoRpwCKTaC8viD/rzon/sUGe/jFnLBDX4DYF6+HhloRWoTT3MLRMkzwNTmZ9qU4acDXebtBL1u+M8HbtPOXZMDVJgTv4V8jWZPJxkma+ES/r6OJbFL/Tw4BKwQ/N0H+Pm+fhj9a+yBjD7dmhqF+92kwIiGWlbpax/12EZw+1ip8amfqV2Hpv6clDQ0alLpzWi/XpFgbBkU5ZB+ltNUoXR6dUy6ZfA345aCvQ1DE/ucFAgMBAAECggEBAMYrJbMFX2iYBolVaTa1ZTgxvU/RsfeOGGq7uWDoJfVucVaNqZ8Jl/D3wyF0FLCCRWZ+8ekPg0Cbhb6GfkI+4di6hGVJZNukgjG89WgnvU+Zj0HM8PqWJgL2ClnoQd1C+D7rYOQN5coA+47WLWEE448F/IWJeLnIhSY8rCMRv/CFC6BQXgftQFGIzpnCPE6vIfVKlbP0gmhBlD15VXUQ9QWuTDY3Nu8dN0JvsRQggH6X2TjX1MhrW/l/ClacV+xBmk8L8FwBxpqvLV19ujYLgUdNIRoiAXC/e7to0LvOhbFREz/61LK92Z/Z47g8xo6+CQ9xKGI+dAarZqC499yCjoECgYEA/uNoiHhBQy2/T+0dCfPjKKaggSx53y+lqCnCgvhy07hO15NRfJaTkXpdyenzRzSp5uO72QzrKxY/KGr6kkQt1acNVBB7T4fz0Jzd89hvBGhXEbJhKdl1qjfuUjp8xfO8Or2M55nAeYJCvHysxgs3fu7kQZtJxGW/coec9a5XaaECgYEA5GO9gvId9jeQokaooalfI+q10igzxsUAWLrA+vkuVfUEWndVVNh1Y8//oACa3fctczXymVSun1RSkdEnkCArPVG22eLp+U+HTqorDG73KRP2Lox3hwspW98ns/cdHdJqd1qjDWuUg1TTbGSxl1IpVN+ZYPjE4G+6TpIUkvDZKuUCgYBQlrQpWeRAiklPyweAaxUqeCyNSvOphlYZKkLuyAD+QerjrBd6jd1QhOD8gzTBEbyaXOy6vqPoNpt3ewOIlXfscmn7Z06lobWMAt0GSSsouJi25rBj2/ahABgg9Y8Xw22DIQVZALrjcDULhVvXLhq4zm1q9N9I8maqnogZAatvoQKBgQDhP+2cxCYAu/SN15phNqZ6yfXg+311QL6CxE2oOTIV3L0abC9gqsu8UVwP9gjHegz9X+uQhhBjW8rDvcCDSPbcV0c7xax1EpakYvhqHtbtUJ6wciFAsyVrUr/ZopK44tnWNTIy/jNPA84xTW5Ji+LvrkebeD7UC913uGNKOPg2cQKBgC/n6d1VXKqhPBU58MdJj+1GoV8BZj/p+ja7jQVT/slYG/DgNho7PZ5+At8ehryYPO2MmPkxr1LiCedclvGpAPeCD9vtST43nuVLU7qkdxmC11iriobbgu3ZkUWSyJoy/3uBgZWHL8bofDsnonLLZFwdZEat0ROkEs3ttEJ9Nqxf";
        // 公钥加密
//        String encryptStr = RsaUtils.encryptByPublicKey(publicKey, text);
        System.out.println("密文 = " + encryptStr);
        // 私钥解密
//        encryptStr="gdKu0MC4M30O2pUTm3IxObYT/XtSwWlp9F8jCoTYt57L2kan0TsKFQlUXoYZSFnXH/bTymEGGNYVQ06MX6ZwjIJYBW73tbQauJ4L69WpfXDOP8z+IYBfSTCQZGO0c1A3Qo5Nq0ZOTImrHvp8lEmyf0B526KOinALLFWxoOxt/f0QCQIrty3AMUpyc4sdB/DTWWYhZVCwY/6cGBUQHrgDaeXXjn9In5kqJZkgEhlxdUNUpAkixYBB/jS0iDyzyPH+9BXhZejypTGtnAkp/bs4qge8Aio2Xnqf/R6uMUEpse6ymJfsfnpfLHfWvJ9ecZqLL+UVWLWjrLebE8rFlsxzag==";
//        String plain = RsaUtils.decryptByPrivateKey(privateKey, encryptStr);

        System.out.println("解密后 = " + plain);
    }

}

客户端RsaUtils.java

package com.figo.myapplication.utils;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import android.util.Base64;
public class RsaUtils {
    /**
     * 加密算法.
     */
    public static final String KEY_ALGORITHM_KEY = "RSA";
    public static final String KEY_ALGORITHM = "RSA/ECB/PKCS1Padding";
    /**
     * 私钥解密.
     *
     * @param privateKeyString 私钥
     * @param text             待解密的文本
     * @return 解密后的文本
     */
    public static String decryptByPrivateKey(String privateKeyString, String text) {
        try {
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decode(privateKeyString,Base64.DEFAULT));
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_KEY);
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] result = cipher.doFinal(Base64.decode(text,Base64.NO_WRAP));
            return new String(result);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 公钥加密.
     *
     * @param publicKeyString 公钥
     * @param text            待加密的文本
     * @return 加密后的文本
     */
    public static String encryptByPublicKey(String publicKeyString, String text) {
        try {
            X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decode(publicKeyString,Base64.DEFAULT));
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM_KEY);
            PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
            Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] result = cipher.doFinal(text.getBytes());
            return new String(Base64.encode(result,Base64.NO_WRAP));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 构建RSA密钥对.
     *
     * @return 生成后的公私钥信息
     */
    public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM_KEY);
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
        //必须使用NO_WRAP,否则会出现换行符,导致服务端无法解密
        String publicKeyString = new String(Base64.encode(rsaPublicKey.getEncoded(),Base64.NO_WRAP));
        String privateKeyString = new String(Base64.encode(rsaPrivateKey.getEncoded(),Base64.NO_WRAP));
        return new RsaKeyPair(publicKeyString, privateKeyString);
    }

    /**
     * RSA密钥对对象.
     */
//    @Data
//    @NoArgsConstructor
//    @AllArgsConstructor
    public static class RsaKeyPair {
        public RsaKeyPair(String publicKey, String privateKey) {
            this.publicKey = publicKey;
            this.privateKey = privateKey;
        }

        /**
         * 公钥.
         */
        private String publicKey;

        /**
         * 私钥.
         */
        private String privateKey;

        public String getPublicKey() {
            return publicKey;
        }

        public void setPublicKey(String publicKey) {
            this.publicKey = publicKey;
        }

        public String getPrivateKey() {
            return privateKey;
        }

        public void setPrivateKey(String privateKey) {
            this.privateKey = privateKey;
        }
    }




    public static void main(String[] args){
        // 生成公私钥对
        RsaKeyPair keyPair = null;
        try {
            keyPair = generateKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        System.out.println("keyPair.getPublicKey() = " + keyPair.getPublicKey());
        System.out.println("keyPair.getPrivateKey() = " + keyPair.getPrivateKey());
        // 公钥加密
        String text = "zhu";
        String encryptStr = RsaUtils.encryptByPublicKey(keyPair.getPublicKey(), text);
        System.out.println("密文 = " + encryptStr);
        // 私钥解密
        String plain = RsaUtils.decryptByPrivateKey(keyPair.getPrivateKey(), encryptStr);
        System.out.println("明文 = " + plain);
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值