区块链技术博客
www.b2bchain.cn

带有dotnet的RSA和PublicKey互操作 – c#程序员分享

本文介绍了带有dotnet的RSA和PublicKey互操作 – c#程序员分享,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

嗨,我正在使用this link中的代码,您能否让我知道为什么签名被验证无效?

Java签署者将BouncyCastleProvider与SHA1withRSA结合使用,这是dotnet验证代码…。

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代码:

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; } 

这是C#中用于签名和验证的代码:

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); } 

参考方案

这里有几个问题。

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

您正在对签名进行Base64解码,但不是Base64编码,而是十六进制编码。

第二个问题是在DecodeX509PublicKey方法中(这是我的错误,因为我在another answer中提供了此代码。)特定的问题行是

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

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

我反复读到ASN.1和.Net API的密钥使用相反的字节序,因此,我的印象是,需要对此字节序进行反转以解决此问题。 (确实,我确实应该像签名验证一样进行测试,而不是仅仅查看内存中的键值>。<)无论如何,请删除这些行,解决编码问题,然后您的签名将正确验证(已成功测试)使用您的样本数据以及我自己的样本数据)。

另外,您的sign方法中的这一行不太正确:

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

到代码中的那一点时,signer对象已经使用默认提供程序实例化了。同样,您不需要每次想要签名某些数据时都添加Bouncy Castle提供程序,它实际上只会在您第一次进行此调用时第一次添加该提供程序,而对于所有后续调用都将忽略它。

此外,signer对象已声明为static,但是您对它的使用不是线程安全的。

您更可能想做的是在静态块中添加提供程序,然后使用Bouncy Castle提供程序显式实例化签名者。如果您未明确指定Bouncy Castle作为提供程序(或使用insertProviderAt将Bouncy Castle添加为最高优先级),则将使用默认提供程序。

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());  ... 

我是PHP的新手,正在尝试使用Datatables jQuery插件。我知道我必须从.php文件中获取数据,然后在数据表中使用它,但是我似乎无法通过ajax将其传递给数据表。我设法从数据库中获取数据,并对其进行json编码,但是后来我不知道如何在我的index.php文件中调用它,并在其中显示它。我究竟做错了什么?这是我的代码:HTML(已编辑): <…

我正在使用Retrofit来获取JSON答复。这是我实施的一部分("/api/report/list") Observable<Bills> listBill(@Query("employee_id") String employeeID); 而条例草案类是-public static class…

我正在尝试使用Retrofit和Gson解析一些JSON。但是,我得到的响应机构是空的。当我尝试从对象中打印信息时,出现NullPointerException。我确保URL正确,并且我也确保POJO也正确。我正在使用jsonschema2pojo来帮助创建POJO类。这是我要解析的JSON{ "?xml": { "@versi…

我有一次噩梦般的时间通过jquery post将数据发送到ASP.NET Controller。这是JSON.stringify之后的数据:[{"scheduleTaskID":"203","task":"Permit","baselineDate":&#03…

我正在约束布局中设计我的应用程序,并将其放置在“滚动视图”下。我想放置更多的Card Views,但是在xml文件的预览中没有放置空间。当布局已满时,我应该在哪里拖放Buttons,TextViews等?我已经处理了文本的滚动视图,但这是另外一回事。我知道我只能输入代码,但是当内容超出定义的屏幕尺寸时,我将无法看到我正在设计的内容时,我将很难这样做。(如果您…

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 带有dotnet的RSA和PublicKey互操作 – c#程序员分享
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们