五维思考

学习要加,骄傲要减,机会要乘,懒惰要除。 http://www.5dthink.cn

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

一、使用场景

Java作为服务端生成一对公私钥,C#作为客户端拥有公钥。

RSA算法这里就不多做介绍了,可参考RSA算法介绍

二、规范

  • 公私钥的形式都是base64字符串
  • 通过公私钥加密后的字符串也是base64字符串

三、测试内容

  • C#用公钥加密,Java用私钥解密
  • Java用私钥加密,C#用公钥解密

四、测试代码

先给出测试代码,后面会有具体的源码。

首先Java作为服务端生成一对公私钥

// 生成一对公私钥
KeyStore keyPair = RSAUtil.createKeys();
System.out.println("公钥:" + keyPair.getPublicKey());
System.out.println("私钥:" + keyPair.getPrivateKey());

公钥

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnEqBL90TN2naZicQyik333/BjG/f5Ib7P0n5j3O5IxqJwvISbim5Xg94u3UBmserNYPQWQt1Jb/HiAG5alrnwWB1XypRyyilVsARXblv1AtwG4Y5BWvDG0jsipmRj581TQSd1w2Nq6rw/xzUH2xzUx8MLmoJu1RiC1oCEUx1CgQIDAQAB

私钥

MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKcSoEv3RM3adpmJxDKKTfff8GMb9/khvs/SfmPc7kjGonC8hJuKbleD3i7dQGax6s1g9BZC3Ulv8eIAblqWufBYHVfKlHLKKVWwBFduW/UC3AbhjkFa8MbSOyKmZGPnzVNBJ3XDY2rqvD/HNQfbHNTHwwuagm7VGILWgIRTHUKBAgMBAAECgYBqDOizT8Hc6U9fJpPjgOb88KkmQBqniUQVpweTXCnlCDEUXpXOJZDk/E+Mb+TxSv5AX8qQVuEgPG7NhniGCCb93qnKi5bU/rw+CQgm9er1pf97aIsvGobnw63bTE1HosWOfuHZTVwGybsQUGM3uPu8xxNaqRSlAknalniO9Y0AAQJBAPS0GZYPMAb+Jb4Yk1gD/joEFp3K5Uedk6dr+rDsNAV1gWBT3dOYjC0oUj5Ju3MQd8RxAm/CG6vDpRm4zRlbW6ECQQCuyRZ99uG+ViLqZlnCvOoTvb02VO/t+JnlW/ZexUIZZnuZPi1OxmnuAnA4prglkMI20KWLvXsxUFss6JGGx3rhAkEA3SWWqgL3yJoOygmzv6t8KjpfpiMjquFB++CeIx6UtQpI7iFdLEmFBZqXGSvReF+9nY70QMQP9d9OajyVPwFNgQJBAJ3nTymXi5PP75VByB/VWcdh5/mYvHWJ3UbHUQmHPdMCsfDcqkP7nqGGlGmpvL07TSoGTziygwQnK2ej6C0SNCECQQCOIO3vrXv4OJzU0dUdkmE5F3Yp/jIzsLpKG1wYE1cv6voRvrMLq8s2LL/5igQLV0XfM//PfQC2hdQIAoORnScc

C#客户端,公钥加密

加密内容:你好rsa

RSA rsa = new RSA();
string content = "你好rsa";
string pubKey = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnEqBL90TN2naZicQyik333/BjG/f5Ib7P0n5j3O5IxqJwvISbim5Xg94u3UBmserNYPQWQt1Jb/HiAG5alrnwWB1XypRyyilVsARXblv1AtwG4Y5BWvDG0jsipmRj581TQSd1w2Nq6rw/xzUH2xzUx8MLmoJu1RiC1oCEUx1CgQIDAQAB";

// 公钥加密
string mi = rsa.EncryptByPublicKey(content, pubKey);

得到加密后的字符串(base64格式):

cLoDffoAxmu6AirAbwpentv7+LwrpD4UZ1OuGxRuhmao0mm6YhK8O3mkQAD235RJ/XlhK6dK8tp4XsBD4FFSCxcoyrnkdayWrGeWtRXRgYWPIpBrperinPXLt0rNYOvNVHWniewyAmPjrU1wfq7BqLZwYyXEGG9QFI83aZIT9xc=

Java服务端,私钥解密

// 公钥加密后的内容
String mi = "cLoDffoAxmu6AirAbwpentv7+LwrpD4UZ1OuGxRuhmao0mm6YhK8O3mkQAD235RJ/XlhK6dK8tp4XsBD4FFSCxcoyrnkdayWrGeWtRXRgYWPIpBrperinPXLt0rNYOvNVHWniewyAmPjrU1wfq7BqLZwYyXEGG9QFI83aZIT9xc=";
// 私钥
String priKey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKcSoEv3RM3adpmJxDKKTfff8GMb9/khvs/SfmPc7kjGonC8hJuKbleD3i7dQGax6s1g9BZC3Ulv8eIAblqWufBYHVfKlHLKKVWwBFduW/UC3AbhjkFa8MbSOyKmZGPnzVNBJ3XDY2rqvD/HNQfbHNTHwwuagm7VGILWgIRTHUKBAgMBAAECgYBqDOizT8Hc6U9fJpPjgOb88KkmQBqniUQVpweTXCnlCDEUXpXOJZDk/E+Mb+TxSv5AX8qQVuEgPG7NhniGCCb93qnKi5bU/rw+CQgm9er1pf97aIsvGobnw63bTE1HosWOfuHZTVwGybsQUGM3uPu8xxNaqRSlAknalniO9Y0AAQJBAPS0GZYPMAb+Jb4Yk1gD/joEFp3K5Uedk6dr+rDsNAV1gWBT3dOYjC0oUj5Ju3MQd8RxAm/CG6vDpRm4zRlbW6ECQQCuyRZ99uG+ViLqZlnCvOoTvb02VO/t+JnlW/ZexUIZZnuZPi1OxmnuAnA4prglkMI20KWLvXsxUFss6JGGx3rhAkEA3SWWqgL3yJoOygmzv6t8KjpfpiMjquFB++CeIx6UtQpI7iFdLEmFBZqXGSvReF+9nY70QMQP9d9OajyVPwFNgQJBAJ3nTymXi5PP75VByB/VWcdh5/mYvHWJ3UbHUQmHPdMCsfDcqkP7nqGGlGmpvL07TSoGTziygwQnK2ej6C0SNCECQQCOIO3vrXv4OJzU0dUdkmE5F3Yp/jIzsLpKG1wYE1cv6voRvrMLq8s2LL/5igQLV0XfM//PfQC2hdQIAoORnScc";
// 解密后的内容
String content = RSAUtil.decryptByPrivateKey(mi, priKey);

System.out.println("你好rsa".equals(content)); // true

至此,公钥加密,私钥解密测试通过。接下来测试Java私钥加密,C#公钥解密

Java私钥加密

加密内容:你好rsa

// 私钥
String priKey = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKcSoEv3RM3adpmJxDKKTfff8GMb9/khvs/SfmPc7kjGonC8hJuKbleD3i7dQGax6s1g9BZC3Ulv8eIAblqWufBYHVfKlHLKKVWwBFduW/UC3AbhjkFa8MbSOyKmZGPnzVNBJ3XDY2rqvD/HNQfbHNTHwwuagm7VGILWgIRTHUKBAgMBAAECgYBqDOizT8Hc6U9fJpPjgOb88KkmQBqniUQVpweTXCnlCDEUXpXOJZDk/E+Mb+TxSv5AX8qQVuEgPG7NhniGCCb93qnKi5bU/rw+CQgm9er1pf97aIsvGobnw63bTE1HosWOfuHZTVwGybsQUGM3uPu8xxNaqRSlAknalniO9Y0AAQJBAPS0GZYPMAb+Jb4Yk1gD/joEFp3K5Uedk6dr+rDsNAV1gWBT3dOYjC0oUj5Ju3MQd8RxAm/CG6vDpRm4zRlbW6ECQQCuyRZ99uG+ViLqZlnCvOoTvb02VO/t+JnlW/ZexUIZZnuZPi1OxmnuAnA4prglkMI20KWLvXsxUFss6JGGx3rhAkEA3SWWqgL3yJoOygmzv6t8KjpfpiMjquFB++CeIx6UtQpI7iFdLEmFBZqXGSvReF+9nY70QMQP9d9OajyVPwFNgQJBAJ3nTymXi5PP75VByB/VWcdh5/mYvHWJ3UbHUQmHPdMCsfDcqkP7nqGGlGmpvL07TSoGTziygwQnK2ej6C0SNCECQQCOIO3vrXv4OJzU0dUdkmE5F3Yp/jIzsLpKG1wYE1cv6voRvrMLq8s2LL/5igQLV0XfM//PfQC2hdQIAoORnScc";
String content = "你好rsa";
String mi = RSAUtil.encryptByPrivateKey(content, priKey);
System.out.println(mi);

加密后的内容:

mm8zoUtHvX8nBnCeZQ6k0aPzbmsvgJiIlyG2QIu9bnsO9BikqUpPOU+4UD6pH60TqQuEJFC1Ynv4D2/K2XryfVLYlwNftuO3Ngem5eVwTkYYAeVnDZ7PlHvemuSV7KPNo/erMhVef1rh5avB/PtSP8tKzmMTJ0hQTVILIaRwhq8=

C#公钥解密

RSA rsa = new RSA();
// Java私钥加密后的内容
string mi = @"mm8zoUtHvX8nBnCeZQ6k0aPzbmsvgJiIlyG2QIu9bnsO9BikqUpPOU+4UD6pH60TqQuEJFC1Ynv4D2/K2XryfVLYlwNftuO3Ngem5eVwTkYYAeVnDZ7PlHvemuSV7KPNo/erMhVef1rh5avB/PtSP8tKzmMTJ0hQTVILIaRwhq8=";
// 公钥
string pubKey = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnEqBL90TN2naZicQyik333/BjG/f5Ib7P0n5j3O5IxqJwvISbim5Xg94u3UBmserNYPQWQt1Jb/HiAG5alrnwWB1XypRyyilVsARXblv1AtwG4Y5BWvDG0jsipmRj581TQSd1w2Nq6rw/xzUH2xzUx8MLmoJu1RiC1oCEUx1CgQIDAQAB";
// 解密后的内容
string content = rsa.DecryptByPublicKey(mi, pubKey);
Assert.IsTrue("你好rsa" == content); // true

五、源码

Java源码

需要apachecommons\-codec.jar

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.11</version>
</dependency>

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * RSA加解密工具<br>
 */
public class RSAUtil {
    public static String RSA_ALGORITHM = "RSA";
    public static String UTF8 = "UTF-8";

    /**
     * 创建公钥私钥
     */
    public static KeyStore createKeys() throws Exception {
        KeyPairGenerator keyPairGeno = KeyPairGenerator.getInstance(RSA_ALGORITHM);
        keyPairGeno.initialize(1024);
        KeyPair keyPair = keyPairGeno.generateKeyPair();

        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

        KeyStore keyStore = new KeyStore();
        keyStore.setPublicKey(Base64.encodeBase64String(publicKey.getEncoded()));
        keyStore.setPrivateKey(Base64.encodeBase64String(privateKey.getEncoded()));
        return keyStore;
    }

    /**
     * 获取公钥对象
     */
    public static RSAPublicKey getPublicKey(byte[] pubKeyData) throws Exception {
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKeyData);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        return (RSAPublicKey) keyFactory.generatePublic(keySpec);
    }

    /**
     * 获取公钥对象
     */
    public static RSAPublicKey getPublicKey(String pubKey) throws Exception {
        return getPublicKey(Base64.decodeBase64(pubKey));

    }

    /**
     * 获取私钥对象
     */
    public static RSAPrivateKey getPrivateKey(String priKey) throws Exception {
        return getPrivateKey(Base64.decodeBase64(priKey));
    }

    /**
     * 通过私钥byte[]将公钥还原,适用于RSA算法
     */
    public static RSAPrivateKey getPrivateKey(byte[] keyBytes) throws Exception {
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);

    }

    public static String encryptByPublicKey(String data, String publicKey) throws Exception {
        return encryptByPublicKey(data, getPublicKey(publicKey));
    }

    /**
     * 公钥加密
     */
    public static String encryptByPublicKey(String data, RSAPublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] bytes = cipher.doFinal(data.getBytes(UTF8));
        return Base64.encodeBase64String(bytes);
    }

    public static String decryptByPublicKey(String data, String rsaPublicKey) throws Exception {
        return decryptByPublicKey(data, getPublicKey(rsaPublicKey));
    }

    /**
     * 公钥解密
     */
    public static String decryptByPublicKey(String data, RSAPublicKey rsaPublicKey) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, rsaPublicKey);
        byte[] inputData = Base64.decodeBase64(data);
        byte[] bytes = cipher.doFinal(inputData);
        return new String(bytes, UTF8);
    }

    public static String encryptByPrivateKey(String data, String privateKey) throws Exception {
        return encryptByPrivateKey(data, getPrivateKey(privateKey));
    }

    /**
     * 私钥加密
     */
    public static String encryptByPrivateKey(String data, RSAPrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        byte[] bytes = cipher.doFinal(data.getBytes(UTF8));
        return Base64.encodeBase64String(bytes);
    }

    public static String decryptByPrivateKey(String data, String privateKey) throws Exception {
        return decryptByPrivateKey(data, getPrivateKey(privateKey));
    }

    /**
     * 私钥解密
     */
    public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] inputData = Base64.decodeBase64(data);
        byte[] bytes = cipher.doFinal(inputData);
        return new String(bytes, UTF8);
    }

    public static class KeyStore {
        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;
        }
    }

}

C#源码

需要下载一个组件

下载地址:http://www.bouncycastle.org/csharp/download/bccrypto-csharp-1.8.2-bin.zip

更多详情:http://www.bouncycastle.org/csharp/

下载后添加dll即可

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;

using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Crypto.Encodings;

namespace Demo
{
    public class RSA
    {
        private static Encoding Encoding_UTF8 = Encoding.UTF8;

        /// <summary>
        /// KEY 结构体
        /// </summary>
        public struct RSAKEY
        {
            /// <summary>
            /// 公钥
            /// </summary>
            public string PublicKey { get; set; }
            /// <summary>
            /// 私钥
            /// </summary>
            public string PrivateKey { get; set; }
        }
        public RSAKEY GetKey()
        {
            //RSA密钥对的构造器
            RsaKeyPairGenerator keyGenerator = new RsaKeyPairGenerator();

            //RSA密钥构造器的参数
            RsaKeyGenerationParameters param = new RsaKeyGenerationParameters(
                Org.BouncyCastle.Math.BigInteger.ValueOf(3),
                new Org.BouncyCastle.Security.SecureRandom(),
                1024,   //密钥长度
                25);
            //用参数初始化密钥构造器
            keyGenerator.Init(param);
            //产生密钥对
            AsymmetricCipherKeyPair keyPair = keyGenerator.GenerateKeyPair();
            //获取公钥和密钥
            AsymmetricKeyParameter publicKey = keyPair.Public;
            AsymmetricKeyParameter privateKey = keyPair.Private;

            SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
            PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey);

            Asn1Object asn1ObjectPublic = subjectPublicKeyInfo.ToAsn1Object();

            byte[] publicInfoByte = asn1ObjectPublic.GetEncoded("UTF-8");
            Asn1Object asn1ObjectPrivate = privateKeyInfo.ToAsn1Object();
            byte[] privateInfoByte = asn1ObjectPrivate.GetEncoded("UTF-8");

            RSAKEY item = new RSAKEY()
            {
                PublicKey = Convert.ToBase64String(publicInfoByte),
                PrivateKey = Convert.ToBase64String(privateInfoByte)
            };
            return item;
        }
        private AsymmetricKeyParameter GetPublicKeyParameter(string keyBase64)
        {
            keyBase64 = keyBase64.Replace("\r", "").Replace("\n", "").Replace(" ", "");
            byte[] publicInfoByte = Convert.FromBase64String(keyBase64);
            Asn1Object pubKeyObj = Asn1Object.FromByteArray(publicInfoByte);//这里也可以从流中读取,从本地导入
            AsymmetricKeyParameter pubKey = PublicKeyFactory.CreateKey(publicInfoByte);
            return pubKey;
        }

        private AsymmetricKeyParameter GetPrivateKeyParameter(string keyBase64)
        {
            keyBase64 = keyBase64.Replace("\r", "").Replace("\n", "").Replace(" ", "");
            byte[] privateInfoByte = Convert.FromBase64String(keyBase64);
            // Asn1Object priKeyObj = Asn1Object.FromByteArray(privateInfoByte);//这里也可以从流中读取,从本地导入
            // PrivateKeyInfo privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateKey);
            AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(privateInfoByte);
            return priKey;
        }

        /// <summary>
        /// 私钥加密
        /// </summary>
        /// <param name="data">加密内容</param>
        /// <param name="privateKey">私钥(Base64后的)</param>
        /// <returns>返回Base64内容</returns>
        public string EncryptByPrivateKey(string data, string privateKey)
        {
            //非对称加密算法,加解密用
            IAsymmetricBlockCipher engine = new Pkcs1Encoding(new RsaEngine());

            //加密
            try
            {
                engine.Init(true, GetPrivateKeyParameter(privateKey));
                byte[] byteData = Encoding_UTF8.GetBytes(data);
                var ResultData = engine.ProcessBlock(byteData, 0, byteData.Length);
                return Convert.ToBase64String(ResultData);
                //Console.WriteLine("密文(base64编码):" + Convert.ToBase64String(testData) + Environment.NewLine);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 私钥解密
        /// </summary>
        /// <param name="data">待解密的内容</param>
        /// <param name="privateKey">私钥(Base64编码后的)</param>
        /// <returns>返回明文</returns>
        public string DecryptByPrivateKey(string data, string privateKey)
        {
            data = data.Replace("\r", "").Replace("\n", "").Replace(" ", "");
            //非对称加密算法,加解密用
            IAsymmetricBlockCipher engine = new Pkcs1Encoding(new RsaEngine());

            //解密
            try
            {
                engine.Init(false, GetPrivateKeyParameter(privateKey));
                byte[] byteData = Convert.FromBase64String(data);
                var ResultData = engine.ProcessBlock(byteData, 0, byteData.Length);
                return Encoding_UTF8.GetString(ResultData);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 公钥加密
        /// </summary>
        /// <param name="data">加密内容</param>
        /// <param name="publicKey">公钥(Base64编码后的)</param>
        /// <returns>返回Base64内容</returns>
        public string EncryptByPublicKey(string data, string publicKey)
        {
            //非对称加密算法,加解密用
            IAsymmetricBlockCipher engine = new Pkcs1Encoding(new RsaEngine());

            //加密
            try
            {
                engine.Init(true, GetPublicKeyParameter(publicKey));
                byte[] byteData = Encoding_UTF8.GetBytes(data);
                var ResultData = engine.ProcessBlock(byteData, 0, byteData.Length);
                return Convert.ToBase64String(ResultData);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 公钥解密
        /// </summary>
        /// <param name="data">待解密的内容</param>
        /// <param name="publicKey">公钥(Base64编码后的)</param>
        /// <returns>返回明文</returns>
        public string DecryptByPublicKey(string data, string publicKey)
        {
            data = data.Replace("\r", "").Replace("\n", "").Replace(" ", "");
            //非对称加密算法,加解密用
            IAsymmetricBlockCipher engine = new Pkcs1Encoding(new RsaEngine());

            //解密
            try
            {
                engine.Init(false, GetPublicKeyParameter(publicKey));
                byte[] byteData = Convert.FromBase64String(data);
                var ResultData = engine.ProcessBlock(byteData, 0, byteData.Length);
                return Encoding_UTF8.GetString(ResultData);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}

此外还可以C#做服务端生成公私钥,Java做客户端。原理是一样的,这里就不测试了,读者可以自行实现。

posted on 2021-04-16 14:32  五维思考  阅读(3226)  评论(0编辑  收藏  举报

QQ群:1. 全栈码农【346906288】2. VBA/VSTO【2660245】