跨平台 RSA 加密 C# 到 Java 和 Java 到 C# [英] Cross Platform RSA Encryption C# to Java and Java to C#

查看:135
本文介绍了跨平台 RSA 加密 C# 到 Java 和 Java 到 C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的 Windows 表单应用程序中生成了一个大小为 1024 的 RSA 密钥.测试应用程序代码如下:

I have generated an RSA key size of 1024 in my Windows form application. The code for the test application is as follows:

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private static CspParameters cspParameters;
        const string keyName = "TestKey1";
        private static RSACryptoServiceProvider devrsa;
        private RSAParameters publicKey;
        private RSAParameters privateKey;

        public Form1()
        {
            InitializeComponent();
        }

        private void BtnGenerate_Click(object sender, EventArgs e)
        {
            cspParameters = new CspParameters();

            cspParameters.KeyContainerName = keyName;
            devrsa = new RSACryptoServiceProvider(1024, cspParameters);
            devrsa.PersistKeyInCsp = true;

            publicKey = devrsa.ExportParameters(false);
            privateKey = devrsa.ExportParameters(true);

            var mod = publicKey.Modulus;
            var exp = publicKey.Exponent;

            var pubKey = new PublicKey
            {
                modulus = Array.ConvertAll(mod, b => unchecked((sbyte)b)),
                exponent = Array.ConvertAll(exp, b => unchecked((sbyte)b)),
            };

            var sPubKey = JsonConvert.SerializeObject(pubKey);

            var bytePubKey = Encoding.ASCII.GetBytes(sPubKey);

            PrintByteArray(bytePubKey);
        }


        public void PrintByteArray(Byte[] bytes)
        {
            var sb = new StringBuilder("new byte[] { ");
            foreach (var b in bytes)
            {
                sb.Append(b + ", ");
            }
            sb.Append("}\n");
            Console.WriteLine(sb.ToString());
        }
    }

public class PublicKey
{
    [JsonProperty("modulus")]
    public SByte[] modulus { get; set; }
    [JsonProperty("exponent")]
    public SByte[] exponent { get; set; }
    public PublicKey()
    {

    }
    public PublicKey(SByte[] modulus, SByte[] exponent)
    {
        this.modulus = modulus;
        this.exponent = exponent;
    }
}

我复制了控制台打印出的字节数组,并将其用作我的测试 Android 应用程序的输入.Test android 应用程序应该将公钥作为输入并使用导入的公钥来加密示例文本字符串.

I take a copy of the console printed out byte array and use it as input in my Test Android Application. The Test android application is supposed to take the public key as input and use the imported public key to encrypt a sample text string.

Android 应用程序代码如下:

The Code for the Android Application is as follows:

class MainActivity : AppCompatActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)

        retrieveElements()
    }


    fun retrieveElements() {
        val request = ByteHelper.pubKey
        var key = ByteHelper.retrieveKey(request)

        val cipher = createCipher(key)

        encrypt(cipher)

    }

    fun createCipher(publicKey: PublicKey): Cipher {
        val modulus = BigInteger(publicKey.modulus)
        val exponent = BigInteger(publicKey.exponent)

        var spec = RSAPublicKeySpec(modulus, exponent)
        var fact = KeyFactory.getInstance(KeyProperties.KEY_ALGORITHM_RSA)

        var publicKey = fact.generatePublic(spec)

        var cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding")
        cipher.init(Cipher.ENCRYPT_MODE, publicKey)
        return cipher
    }

    fun encrypt(cipher: Cipher)
    {
        val testString = "This is a test string"

        val stringBytes = testString.toByteArray(StandardCharsets.US_ASCII)

        val encryptedBytes = cipher.doFinal(stringBytes)

    }
}

class ByteHelper
{
    companion object
    {
        val pubKey = byteArrayOf( 123, 34, 109, 111, 100, 117, 108, 117, 115, 34, 58, 91, 45, 55, 49, 44, 45, 51, 50, 44, 45, 55, 44, 45, 49,
            48, 55, 44, 45, 51, 54, 44, 45, 51, 54, 44, 51, 54, 44, 45, 56, 44, 45, 51, 48, 44, 45, 49, 50, 53, 44, 45, 52, 44, 49,
            48, 48, 44, 45, 54, 49, 44, 45, 56, 48, 44, 45, 55, 53, 44, 50, 44, 52, 44, 49, 50, 51, 44, 52, 50, 44, 53, 54, 44, 45,
            53, 49, 44, 54, 55, 44, 45, 55, 44, 57, 55, 44, 49, 48, 54, 44, 45, 49, 49, 55, 44, 45, 49, 49, 57, 44, 45, 49, 49, 54,
            44, 45, 49, 50, 50, 44, 45, 50, 53, 44, 45, 55, 51, 44, 45, 51, 51, 44, 55, 49, 44, 45, 54, 53, 44, 53, 48, 44, 51, 50,
            44, 45, 51, 49, 44, 45, 49, 48, 56, 44, 45, 55, 49, 44, 45, 49, 49, 51, 44, 53, 53, 44, 45, 49, 49, 48, 44, 53, 55, 44,
            45, 55, 50, 44, 50, 44, 51, 49, 44, 51, 52, 44, 45, 49, 49, 48, 44, 55, 48, 44, 45, 57, 54, 44, 45, 57, 48, 44, 52, 52,
            44, 49, 49, 48, 44, 45, 49, 48, 55, 44, 45, 50, 53, 44, 45, 49, 56, 44, 49, 53, 44, 45, 51, 50, 44, 45, 56, 52, 44, 45,
            53, 44, 51, 53, 44, 45, 49, 48, 44, 45, 54, 49, 44, 45, 53, 51, 44, 49, 50, 49, 44, 45, 50, 50, 44, 56, 53, 44, 45, 49,
            48, 48, 44, 45, 52, 55, 44, 57, 51, 44, 45, 49, 49, 54, 44, 57, 44, 49, 51, 44, 55, 50, 44, 49, 50, 49, 44, 45, 52, 48,
            44, 45, 54, 53, 44, 49, 48, 53, 44, 45, 52, 52, 44, 45, 51, 50, 44, 51, 53, 44, 49, 49, 54, 44, 49, 49, 57, 44, 50, 56,
            44, 45, 55, 53, 44, 52, 53, 44, 56, 52, 44, 45, 53, 55, 44, 49, 55, 44, 49, 49, 44, 45, 49, 53, 44, 45, 52, 51, 44, 45,
            56, 55, 44, 49, 51, 44, 45, 52, 57, 44, 51, 53, 44, 55, 49, 44, 45, 51, 48, 44, 45, 49, 48, 57, 44, 45, 50, 52, 44, 51,
            49, 44, 45, 51, 50, 44, 50, 54, 44, 45, 51, 56, 44, 49, 49, 56, 44, 45, 52, 49, 44, 45, 51, 52, 44, 49, 57, 44, 45, 49,
            50, 50, 44, 45, 54, 51, 44, 52, 48, 44, 50, 53, 44, 57, 54, 44, 45, 56, 55, 44, 52, 53, 44, 45, 53, 48, 44, 45, 53, 54,
            44, 45, 55, 48, 44, 45, 49, 48, 55, 44, 45, 56, 54, 44, 52, 55, 44, 49, 48, 53, 44, 45, 51, 44, 45, 53, 57, 44, 53, 52,
            44, 45, 49, 50, 49, 44, 56, 52, 44, 45, 51, 93, 44, 34, 101, 120, 112, 111, 110, 101, 110, 116, 34, 58, 91, 49, 44, 48,
            44, 49, 93, 125)

        fun retrieveKey(bytes: ByteArray) : PublicKey
        {
            var jsonString = String(bytes, Charset.forName("US-ASCII"))

            var publicKey = Gson().fromJson(jsonString, PublicKey::class.java)

            return publicKey
        }
    }
}

data class PublicKey(
    @SerializedName("modulus") var modulus: ByteArray,
    @SerializedName("exponent") var exponent: ByteArray
) {
    constructor() : this(ByteArray(0), ByteArray(0))
}

但是,当我运行我的应用程序的 Android 版本时.我收到以下错误.

However, when I run the Android version of my application. I get the following error.

com.android.org.bouncycastle.crypto.DataLengthException: input too large for RSA cipher.
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2666)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2727)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1478)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6121)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
     Caused by: com.android.org.bouncycastle.crypto.DataLengthException: input too large for RSA cipher.
        at com.android.org.bouncycastle.crypto.engines.RSACoreEngine.convertInput(RSACoreEngine.java:115)
        at com.android.org.bouncycastle.crypto.engines.RSABlindedEngine.processBlock(RSABlindedEngine.java:95)
        at com.android.org.bouncycastle.crypto.encodings.OAEPEncoding.encodeBlock(OAEPEncoding.java:199)
        at com.android.org.bouncycastle.crypto.encodings.OAEPEncoding.processBlock(OAEPEncoding.java:131)
        at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineDoFinal(CipherSpi.java:475)
        at javax.crypto.Cipher.doFinal(Cipher.java:2056)
        at com.touchsides.myapplication.MainActivity.encrypt(MainActivity.kt:54)

推荐答案

在 createCipher 函数中,与将 ByteArray 转换为 BigInteger 相关的问题.

Within the createCipher function, the issue related to the conversion of the ByteArray to a BigInteger.

val modulus = BigInteger(1, publicKey.modulus)
val exponent = BigInteger(1, publicKey.exponent)

var spec = RSAPublicKeySpec(modulus, exponent)
var fact = KeyFactory.getInstance(KeyProperties.KEY_ALGORITHM_RSA)

var publicKey = fact.generatePublic(spec)

var cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding")
cipher.init(Cipher.ENCRYPT_MODE, publicKey)

为了允许在另一端解密,密码实例需要从:

To allow for decryption on the other side the cipher instance needs to be changed from :

RSA/ECB/OAEPWithSHA-256AndMGF1Padding => RSA/ECB/OAEPWithSHA-1AndMGF1Padding

这篇关于跨平台 RSA 加密 C# 到 Java 和 Java 到 C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆