RSA和公钥互操作与DOTNET [英] RSA and PublicKey interop with dotnet

查看:152
本文介绍了RSA和公钥互操作与DOTNET的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的此链接,可以让我知道为什么签名验证是不工作?



Java的签名者使用的 BouncyCastleProvider 的用的 SHA1withRSA 的,这里是DOTNET验证码....

 使用系统; 
:使用System.IO;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用System.Security.Cryptography;使用System.Security.Cryptography.X509Certificates
;
使用Org.BouncyCastle.Asn1;
使用Org.BouncyCastle.Crypto;使用Org.BouncyCastle.Crypto.Parameters
;
使用Org.BouncyCastle.OpenSsl;
使用Org.BouncyCastle.Security;使用Org.BouncyCastle.Utilities.Encoders
;

命名ConsoleApplication1
{
类节目
{
静态无效的主要(字串[] args)
{
串PUBKEY = @MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMf54mcK3EYJn9tT9BhRoTX + 8AkqojIyeSfog9ncYEye0VXyBULGg2lAQsDRt8lZsvPioORZW7eB6IKawshoWUsCAwEAAQ ==;
特征码=770bb2610bf6b2602ce2b3ad8489054f4ed59c9b0c9299327f76ecbc60a8bb9a725cfae901fc189d4bafcf73a2f4aed8dffe9842f7b6196ddfcd040c7271c7ca;
字符串signData =C2:AE:D6:2B:DF:A4;
字节[] = expectedSig System.Convert.FromBase64String(签字);
字节[] = baKey System.Convert.FromBase64String(PUBKEY);

字节[]数据= Encoding.UTF8.GetBytes(signData);

//Console.WriteLine(p.VerifyData(data,新SHA1CryptoServiceProvider(),expectedSig));

/ *初始化ALG * /
ISigner签名= SignerUtilities.GetSigner(SHA1withRSA);
/ *填充键* /
signer.Init(假,DecodeX509PublicKey2(baKey));
/ *计算签名,看它是否符合* /
signer.BlockUpdate(数据,0,data.Length);

Console.WriteLine(signer.VerifySignature(expectedSig));
Console.In.ReadLine();
}

公共静态RsaKeyParameters DecodeX509PublicKey2(字节[] x509key)
{
的byte [] SeqOID = {0x2A,0x86可以,0x48,0x86可以,0xF7,0X0D, 0×01,0×01,0×01};

的MemoryStream毫秒​​=新的MemoryStream(x509key);
BinaryReader读卡器=新BinaryReader(毫秒);

如果(reader.ReadByte()==的0x30)
ReadASNLength(读卡器); //跳过大小
,否则
返回NULL;

INT identifierSize = 0; //对象标识符部分
的总长度,如果(reader.ReadByte()==的0x30)
identifierSize = ReadASNLength(读卡器);
,否则
返回NULL;

如果(reader.ReadByte()== 0×06)//是下一个元素的对象标识符?
{
INT oidLength = ReadASNLength(读卡器);
字节[] = oidBytes新的字节[oidLength]
reader.Read(oidBytes,0,oidBytes.Length);
如果(oidBytes.SequenceEqual(SeqOID)== FALSE)//为对象标识符rsaEncryption PKCS#1?
返回NULL;

INT remainingBytes = identifierSize - 2 - oidBytes.Length;
reader.ReadBytes(remainingBytes);
}

如果(reader.ReadByte()== 0×03)//是下一个元素的比特串?
{
ReadASNLength(读卡器); //跳过大小
reader.ReadByte(); //跳过未使用的位指示
如果(reader.ReadByte()==的0x30)
{
ReadASNLength(读卡器); //跳过大小
如果(reader.ReadByte()== 0×02)//是一个整数?
{
INT modulusSize = ReadASNLength(读卡器);
字节[] =模新的字节[modulusSize]
reader.Read(模数,0,modulus.Length);
如果(模数[0] == 0×00)//如果是0
{
字节[] = tempModulus新的字节[modulus.Length - 1]剥离的第一个字节;
Array.Copy(模量,1,tempModulus,0,modulus.Length - 1);
模量= tempModulus;
}
Array.Reverse(模数); //转换为大端

如果(reader.ReadByte()== 0×02)//是一个整数?
{
INT exponentSize = ReadASNLength(读卡器);
的byte []指数为新的字节[exponentSize]
reader.Read(指数,0,exponent.Length);
Array.Reverse(指数); //转换为大端

// RSAParameters RSAKeyInfo =新RSAParameters();
//RSAKeyInfo.Modulus =模量;
//RSAKeyInfo.Exponent =指数;

返回MakeKey(BitConverter.ToString(模数).Replace( - 的String.Empty),BitConverter.ToString(指数).Replace( - 的String.Empty),FALSE);
}
}
}
}
返回NULL;
}

公共静态RsaKeyParameters MakeKey(字符串modulusHexString,字符串exponentHexString,布尔isPrivateKey)
{
无功模量=新Org.BouncyCastle.Math.BigInteger(modulusHexString, 16);
VAR指数=新Org.BouncyCastle.Math.BigInteger(exponentHexString,16);

返回新RsaKeyParameters(isPrivateKey,模量,指数);
}

公共静态的RSACryptoServiceProvider DecodeX509PublicKey(字节[] x509key)
{
的byte [] SeqOID = {0x2A,0x86可以,0x48,0x86可以,0xF7,0X0D, 0×01,0×01,0×01};

的MemoryStream毫秒​​=新的MemoryStream(x509key);
BinaryReader读卡器=新BinaryReader(毫秒);

如果(reader.ReadByte()==的0x30)
ReadASNLength(读卡器); //跳过大小
,否则
返回NULL;

INT identifierSize = 0; //对象标识符部分
的总长度,如果(reader.ReadByte()==的0x30)
identifierSize = ReadASNLength(读卡器);
,否则
返回NULL;

如果(reader.ReadByte()== 0×06)//是下一个元素的对象标识符?
{
INT oidLength = ReadASNLength(读卡器);
字节[] = oidBytes新的字节[oidLength]
reader.Read(oidBytes,0,oidBytes.Length);
如果(oidBytes.SequenceEqual(SeqOID)== FALSE)//为对象标识符rsaEncryption PKCS#1?
返回NULL;

INT remainingBytes = identifierSize - 2 - oidBytes.Length;
reader.ReadBytes(remainingBytes);
}

如果(reader.ReadByte()== 0×03)//是下一个元素的比特串?
{
ReadASNLength(读卡器); //跳过大小
reader.ReadByte(); //跳过未使用的位指示
如果(reader.ReadByte()==的0x30)
{
ReadASNLength(读卡器); //跳过大小
如果(reader.ReadByte()== 0×02)//是一个整数?
{
INT modulusSize = ReadASNLength(读卡器);
字节[] =模新的字节[modulusSize]
reader.Read(模数,0,modulus.Length);
如果(模数[0] == 0×00)//如果是0
{
字节[] = tempModulus新的字节[modulus.Length - 1]剥离的第一个字节;
Array.Copy(模量,1,tempModulus,0,modulus.Length - 1);
模量= tempModulus;
}
Array.Reverse(模数); //转换为大端

如果(reader.ReadByte()== 0×02)//是一个整数?
{
INT exponentSize = ReadASNLength(读卡器);
的byte []指数为新的字节[exponentSize]
reader.Read(指数,0,exponent.Length);
Array.Reverse(指数); //转换为大端

的RSACryptoServiceProvider RS​​A =新的RSACryptoServiceProvider();
RSAParameters RSAKeyInfo =新RSAParameters();
RSAKeyInfo.Modulus =模量;
RSAKeyInfo.Exponent =指数;
RSA.ImportParameters(RSAKeyInfo);
返回RSA;
}
}
}
}
返回NULL;
}

公共静态INT ReadASNLength(BinaryReader读卡器)
{
//注:该方法只读取长度可达4个字节只要
/ /这是大多数情况令人满意。
INT长度= reader.ReadByte();
如果((长度安培; 0x00000080)== 0x00000080)//是长度大于1字节
{
诠释计数=长度放大器; 0x0000000f;
字节[] = lengthBytes的新的字节[4];
reader.Read(lengthBytes的,4 - 计数,计数);
Array.Reverse(lengthBytes的); //
长度= BitConverter.ToInt32(lengthBytes的,0);
}
返回长度;
}
}
}



Java代码用于签名的签名数据:

 私有静态最终java.security.Signature中的签名; 
静态最后弦乐转型=RSA / ECB / PKCS1Padding
静态{
尝试{
=签名java.security.Signature.getInstance(SHA1withRSA);
}赶上(抛出:NoSuchAlgorithmException五){
e.printStackTrace();
}
}

静态串号(字符串明文){
串签= NULL;
尝试{
Security.addProvider(新org.bouncycastle.jce.provider.BouncyCastleProvider());
字节[]数据= clearText.getBytes(UTF-8);
signer.initSign(getPrivateKey());
signer.update(数据);
字节[] =的DigitalSignature signer.sign();
// - toHex
=签署org.apache.commons.codec.binary.Hex.encodeHexString(的DigitalSignature);
}赶上(例外五){
e.printStackTrace();
}
返回签署;
}

密钥对generateKeyPair(){
密钥对KP = NULL;
//生成密钥对
的KeyPairGenerator KPG;
SecureRandom的SecureRandom的;
尝试{
KPG = KeyPairGenerator.getInstance(RSA);
SecureRandom的= SecureRandom.getInstance(SHA1PRNG,SUN);
secureRandom.setSeed(secureRandomSeed);
kpg.initialize(512,SecureRandom的);
KP = kpg.generateKeyPair();
}赶上(例外五){
e.printStackTrace();
}
返回KP;
}

下面是在C#中的标志代码和验证:

 静态无效TEST3()
{
AsymmetricCipherKeyPair键= generateNewKeys();
/ *初始化ALG * /
ISigner SIG = SignerUtilities.GetSigner(SHA1withRSA);

/ *填充键* /
sig.Init(真,keys.Private);

/ *获取字节从字符串* /
VAR字节= Encoding.UTF8.GetBytes(signData)签署;

/ *计算器签名* /
sig.BlockUpdate(字节,0,bytes.Length);
字节[] =签名sig.GenerateSignature();

/ *基于64编码的签名所以它支持8-bit * /
VAR signedString = Convert.ToBase64String(签字);
Console.WriteLine(signedString);

串expectedSignature = signedString;
/ *初始化ALG * /
ISigner签名= SignerUtilities.GetSigner(SHA1withRSA);

/ *填充键* /
signer.Init(假,keys.Public);

/ *获取签名改成字节* /
VAR expectedSig = Convert.FromBase64String(expectedSignature);

/ *获取字节从字符串* /
VAR msgBytes = Encoding.UTF8.GetBytes(signData)签署;

/ *计算签名,看它是否符合* /
signer.BlockUpdate(msgBytes,0,msgBytes.Length);
/ *验证码:* /
布尔结果= signer.VerifySignature(expectedSig);
Console.WriteLine(结果);
}


解决方案

这里有一对夫妇的问题的问题

 特征码=770bb ... 1c7ca; 

字节[] = expectedSig System.Convert.FromBase64String(签字);

您是Base64编码的签名进行解码,但它不是Base64编码,它的十六进制编码。



第二个问题是在 DecodeX509PublicKey 方法(这诚然是我的错,因为我提供了的another回答)的特定问题行

  Array.Reverse(模数); //转换为大端

  Array.Reverse(指数); //转换为大端



我反复读了ASN.1和.Net API使用他们的对面钥匙endieness,所以我的印象是,所需要的endieness被逆转考虑到这一点。 (我确实应该这样做喜欢你的签名验证测试,以确保,而不是仅仅看在内存中的键值><)无论如何,删除这些行,解决编码的问题,你的签名将正确验证(成功使用您的样本数据,以及我自己的)进行测试。



另外,该线路在标志方法ISN ŧ完全正确:

  Security.addProvider(新org.bouncycastle.jce.provider.BouncyCastleProvider()); 



到时候你在代码中,签署者这一点对象已使用的默认提供实例化。此外,你不需要是要签署一些数据每次加的充气城堡供应商,它只会实际添加提供程序的第一次拨打这个电话,并会忽略它的所有后续调用。



此外,签名对象declaired 静态,但你的使用它不是线程安全的。



您更有可能想要做的是增加供应商在静态块,然后明确地使用充气城堡供应商实例化签名。如果你没有明确指定充气城堡的供应商(或使用 insertProviderAt 添加充气城堡作为最高优先级),默认的供应商将被使用。



 静态{
尝试{
Security.addProvider(新org.bouncycastle.jce.provider.BouncyCastleProvider());
}赶上(例外五){
e.printStackTrace();
}
}

...

串签= NULL;
尝试{
java.security.Signature中的签名= java.security.Signature.getInstance(SHA1withRSA,BC);
字节[]数据= clearText.getBytes(UTF-8);
signer.initSign(getPrivateKey());

...


Hi I am using code from this link, Can you let me know why signature is verify is not working?

Java signer is using BouncyCastleProvider with SHA1withRSA, here is dotnet verify code....

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string pubkey = @"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMf54mcK3EYJn9tT9BhRoTX+8AkqojIyeSfog9ncYEye0VXyBULGg2lAQsDRt8lZsvPioORZW7eB6IKawshoWUsCAwEAAQ==";
            String signature = "770bb2610bf6b2602ce2b3ad8489054f4ed59c9b0c9299327f76ecbc60a8bb9a725cfae901fc189d4bafcf73a2f4aed8dffe9842f7b6196ddfcd040c7271c7ca";
            String signData = "C2:AE:D6:2B:DF:A4";
            byte[] expectedSig = System.Convert.FromBase64String(signature);
            byte[] baKey = System.Convert.FromBase64String(pubkey);

            byte[] data = Encoding.UTF8.GetBytes(signData);

            //Console.WriteLine(p.VerifyData(data, new SHA1CryptoServiceProvider(), expectedSig));

            /* Init alg */
            ISigner signer = SignerUtilities.GetSigner("SHA1withRSA");
            /* Populate key */
            signer.Init(false, DecodeX509PublicKey2(baKey));
            /* Calculate the signature and see if it matches */
            signer.BlockUpdate(data, 0, data.Length);

            Console.WriteLine(signer.VerifySignature(expectedSig));
            Console.In.ReadLine();
        }

        public static RsaKeyParameters DecodeX509PublicKey2(byte[] x509key)
        {
            byte[] SeqOID = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };

            MemoryStream ms = new MemoryStream(x509key);
            BinaryReader reader = new BinaryReader(ms);

            if (reader.ReadByte() == 0x30)
                ReadASNLength(reader); //skip the size
            else
                return null;

            int identifierSize = 0; //total length of Object Identifier section
            if (reader.ReadByte() == 0x30)
                identifierSize = ReadASNLength(reader);
            else
                return null;

            if (reader.ReadByte() == 0x06) //is the next element an object identifier?
            {
                int oidLength = ReadASNLength(reader);
                byte[] oidBytes = new byte[oidLength];
                reader.Read(oidBytes, 0, oidBytes.Length);
                if (oidBytes.SequenceEqual(SeqOID) == false) //is the object identifier rsaEncryption PKCS#1?
                    return null;

                int remainingBytes = identifierSize - 2 - oidBytes.Length;
                reader.ReadBytes(remainingBytes);
            }

            if (reader.ReadByte() == 0x03) //is the next element a bit string?
            {
                ReadASNLength(reader); //skip the size
                reader.ReadByte(); //skip unused bits indicator
                if (reader.ReadByte() == 0x30)
                {
                    ReadASNLength(reader); //skip the size
                    if (reader.ReadByte() == 0x02) //is it an integer?
                    {
                        int modulusSize = ReadASNLength(reader);
                        byte[] modulus = new byte[modulusSize];
                        reader.Read(modulus, 0, modulus.Length);
                        if (modulus[0] == 0x00) //strip off the first byte if it's 0
                        {
                            byte[] tempModulus = new byte[modulus.Length - 1];
                            Array.Copy(modulus, 1, tempModulus, 0, modulus.Length - 1);
                            modulus = tempModulus;
                        }
                        Array.Reverse(modulus); //convert to big-endian

                        if (reader.ReadByte() == 0x02) //is it an integer?
                        {
                            int exponentSize = ReadASNLength(reader);
                            byte[] exponent = new byte[exponentSize];
                            reader.Read(exponent, 0, exponent.Length);
                            Array.Reverse(exponent); //convert to big-endian

                            //RSAParameters RSAKeyInfo = new RSAParameters();
                            //RSAKeyInfo.Modulus = modulus;
                            //RSAKeyInfo.Exponent = exponent;

                            return MakeKey(BitConverter.ToString(modulus).Replace("-", string.Empty), BitConverter.ToString(exponent).Replace("-", string.Empty), false);
                        }
                    }
                }
            }
            return null;
        }

        public static RsaKeyParameters MakeKey(String modulusHexString, String exponentHexString, bool isPrivateKey)
        {
            var modulus = new Org.BouncyCastle.Math.BigInteger(modulusHexString, 16);
            var exponent = new Org.BouncyCastle.Math.BigInteger(exponentHexString, 16);

            return new RsaKeyParameters(isPrivateKey, modulus, exponent);
        }

        public static RSACryptoServiceProvider DecodeX509PublicKey(byte[] x509key)
        {
            byte[] SeqOID = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 };

            MemoryStream ms = new MemoryStream(x509key);
            BinaryReader reader = new BinaryReader(ms);

            if (reader.ReadByte() == 0x30)
                ReadASNLength(reader); //skip the size
            else
                return null;

            int identifierSize = 0; //total length of Object Identifier section
            if (reader.ReadByte() == 0x30)
                identifierSize = ReadASNLength(reader);
            else
                return null;

            if (reader.ReadByte() == 0x06) //is the next element an object identifier?
            {
                int oidLength = ReadASNLength(reader);
                byte[] oidBytes = new byte[oidLength];
                reader.Read(oidBytes, 0, oidBytes.Length);
                if (oidBytes.SequenceEqual(SeqOID) == false) //is the object identifier rsaEncryption PKCS#1?
                    return null;

                int remainingBytes = identifierSize - 2 - oidBytes.Length;
                reader.ReadBytes(remainingBytes);
            }

            if (reader.ReadByte() == 0x03) //is the next element a bit string?
            {
                ReadASNLength(reader); //skip the size
                reader.ReadByte(); //skip unused bits indicator
                if (reader.ReadByte() == 0x30)
                {
                    ReadASNLength(reader); //skip the size
                    if (reader.ReadByte() == 0x02) //is it an integer?
                    {
                        int modulusSize = ReadASNLength(reader);
                        byte[] modulus = new byte[modulusSize];
                        reader.Read(modulus, 0, modulus.Length);
                        if (modulus[0] == 0x00) //strip off the first byte if it's 0
                        {
                            byte[] tempModulus = new byte[modulus.Length - 1];
                            Array.Copy(modulus, 1, tempModulus, 0, modulus.Length - 1);
                            modulus = tempModulus;
                        }
                        Array.Reverse(modulus); //convert to big-endian

                        if (reader.ReadByte() == 0x02) //is it an integer?
                        {
                            int exponentSize = ReadASNLength(reader);
                            byte[] exponent = new byte[exponentSize];
                            reader.Read(exponent, 0, exponent.Length);
                            Array.Reverse(exponent); //convert to big-endian

                            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
                            RSAParameters RSAKeyInfo = new RSAParameters();
                            RSAKeyInfo.Modulus = modulus;
                            RSAKeyInfo.Exponent = exponent;
                            RSA.ImportParameters(RSAKeyInfo);
                            return RSA;
                        }
                    }
                }
            }
            return null;
        }

        public static int ReadASNLength(BinaryReader reader)
        {
            //Note: this method only reads lengths up to 4 bytes long as
            //this is satisfactory for the majority of situations.
            int length = reader.ReadByte();
            if ((length & 0x00000080) == 0x00000080) //is the length greater than 1 byte
            {
                int count = length & 0x0000000f;
                byte[] lengthBytes = new byte[4];
                reader.Read(lengthBytes, 4 - count, count);
                Array.Reverse(lengthBytes); //
                length = BitConverter.ToInt32(lengthBytes, 0);
            }
            return length;
        }
    }
}

Java code used to sign signature data:

private static final java.security.Signature signer;
static final String transformation = "RSA/ECB/PKCS1Padding";
static {
    try {
        signer = java.security.Signature.getInstance("SHA1withRSA");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}

static String sign(String clearText) {
    String signed = null;
    try {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        byte[] data = clearText.getBytes("UTF-8");
        signer.initSign(getPrivateKey());
        signer.update(data);
        byte[] digitalSignature = signer.sign();
        //--toHex
        signed = org.apache.commons.codec.binary.Hex.encodeHexString(digitalSignature);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return signed;
}

KeyPair generateKeyPair() {
    KeyPair kp = null;
    // Generate a key-pair
    KeyPairGenerator kpg;
    SecureRandom secureRandom;
    try {
        kpg = KeyPairGenerator.getInstance("RSA");
        secureRandom = SecureRandom.getInstance("SHA1PRNG", "SUN");
        secureRandom.setSeed(secureRandomSeed);
        kpg.initialize(512, secureRandom);
        kp = kpg.generateKeyPair();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return kp;
}

Here is code in C# that signs and verifies:

static void test3()
{
    AsymmetricCipherKeyPair keys = generateNewKeys();
    /* Init alg */
    ISigner sig = SignerUtilities.GetSigner("SHA1withRSA");

    /* Populate key */
    sig.Init(true, keys.Private);

    /* Get the bytes to be signed from the string */
    var bytes = Encoding.UTF8.GetBytes(signData);

    /* Calc the signature */
    sig.BlockUpdate(bytes, 0, bytes.Length);
    byte[] signature = sig.GenerateSignature();

    /* Base 64 encode the sig so its 8-bit clean */
    var signedString = Convert.ToBase64String(signature);
    Console.WriteLine(signedString);

    string expectedSignature = signedString;
    /* Init alg */
    ISigner signer = SignerUtilities.GetSigner("SHA1withRSA");

    /* Populate key */
    signer.Init(false, keys.Public);

    /* Get the signature into bytes */
    var expectedSig = Convert.FromBase64String(expectedSignature);

    /* Get the bytes to be signed from the string */
    var msgBytes = Encoding.UTF8.GetBytes(signData);

    /* Calculate the signature and see if it matches */
    signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
    /*Verify*/
    bool result= signer.VerifySignature(expectedSig);
    Console.WriteLine(result);
}

解决方案

There's a couple problems problems here.

String signature = "770bb ... 1c7ca";
...
byte[] expectedSig = System.Convert.FromBase64String(signature);

You're Base64 decoding the signature, but it's not Base64 encoded, it's Hex encoded.

The second problem is in the DecodeX509PublicKey methods (which admittedly is my mistake because I provided this code in another answer.) The specific problem lines are

Array.Reverse(modulus); //convert to big-endian

and

Array.Reverse(exponent); //convert to big-endian

I repeatedly read that the ASN.1 and the .Net API use opposite endieness for their keys, and so I was under the impression that the endieness needed to be reversed to account for this. (I really should have done a test like your signature verification to be sure, rather than just looking at the key values in memory >.<) Regardless, remove these lines, fix the encoding problem, and your signature will verify properly (successfully tested using your sample data as well as my own).

Also, this line in your sign method isn't quite right:

Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

By the time you get to that point in the code, the signer object has already been instantiated using the default provider. Also, you don't need to be adding the Bouncy Castle provider each time you want to sign some data, it will only actually add the provider the first time you make this call and will ignore it for all subsequent calls.

Further, the signer object is declaired static, but your usage of it is not thread safe.

What you more likely want to do is add the provider in the static block and then instantiate the signer explicitly using the Bouncy Castle provider. If you don't explicitly specify Bouncy Castle as the provider (or add Bouncy Castle as the highest priority using insertProviderAt), the default provider will be used instead.

static {
    try {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

...

String signed = null;
try {
    java.security.Signature signer = java.security.Signature.getInstance("SHA1withRSA", "BC");
    byte[] data = clearText.getBytes("UTF-8");
    signer.initSign(getPrivateKey());

...

这篇关于RSA和公钥互操作与DOTNET的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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