英文:
Should I use MessageDigest to verify a digital signature that signed in C#?
问题
以下是翻译好的内容:
C#:
static string SignData(string message, RSAParameters privateKey)
{
byte[] signedBytes;
using (var rsa = new RSACryptoServiceProvider())
{
var encoder = new UTF8Encoding();
byte[] originalData = encoder.GetBytes(message);
rsa.ImportParameters(privateKey);
signedBytes = rsa.SignData(originalData, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
rsa.PersistKeyInCsp = false;
}
return Convert.ToBase64String(signedBytes);
}
Java:
static boolean verifySignature512(String message, String sign, PublicKey publicKey) throws Exception {
// MessageDigest digest = MessageDigest.getInstance("SHA-512");
// byte[] contentDigest = digest.digest(message.getBytes(Charset.forName("UTF-8")));
Signature signature = Signature.getInstance("SHA512withRSA");
signature.initVerify(publicKey);
signature.update(message.getBytes(Charset.forName("UTF-8")));
return signature.verify(Base64.getDecoder().decode(sign));
}
请注意,上述内容中的代码片段已经根据你的要求进行了翻译。如果你有任何关于代码部分的问题或需要进一步的帮助,请随时提问。
英文:
I'm new in Java and want to sign some data in c# and verify in Java with RSA and SHA512.
C#:
static string SignData(string message, RSAParameters privateKey)
{
byte[] signedBytes;
using (var rsa = new RSACryptoServiceProvider())
{
var encoder = new UTF8Encoding();
byte[] originalData = encoder.GetBytes(message);
rsa.ImportParameters(privateKey);
signedBytes = rsa.SignData(originalData, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
rsa.PersistKeyInCsp = false;
}
return Convert.ToBase64String(signedBytes);
}
Java:
static boolean verifySignature512(String message, String sign, PublicKey publicKey) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-512");
byte[] contentDigest = digest.digest(message.getBytes(Charset.forName("UTF-8")));
Signature signature = Signature.getInstance("Sha512withRSA");
signature.initVerify(publicKey);
signature.update(contentDigest);
return signature.verify(Base64.getDecoder().decode(sign));
}
I used RSA and public and private keys. Java function always return false with no error or exception.
If I remove MessageDigest like below it starts working, Is it ok and secure?
static boolean verifySignature512(String message, String sign, PublicKey publicKey) throws Exception {
// MessageDigest digest = MessageDigest.getInstance("SHA-512");
// byte[] contentDigest = digest.digest(message.getBytes(Charset.forName("UTF-8")));
Signature signature = Signature.getInstance("Sha512withRSA");
signature.initVerify(publicKey);
signature.update(message.getBytes(Charset.forName("UTF-8")));
return signature.verify(Base64.getDecoder().decode(sign));
}
答案1
得分: 1
以下是翻译好的内容:
C#-code:
using System;
using System.Security.Cryptography;
using System.Text;
class RSACSPSample {
static void Main() {
try {
Console.WriteLine("Should I use MessageDigest to verify a digital signature that signed in C#?");
// 创建UnicodeEncoder以在字节数组和字符串之间进行转换。
ASCIIEncoding ByteConverter = new ASCIIEncoding();
string message = "this is the important message to sign";
// 获取私钥和公钥 ### 示例和不安全的512位RSA密钥对
var privateKey = "<RSAKeyValue><Modulus>mfgthqgvK5P6kP00ojzA68+tGMwjEacduojFSukazKPXrZ8Q5XjzfqgJmDQ3wcWe3hWK92O3z/tmAuN47KA0ZQ==</Modulus><Exponent>AQAB</Exponent><P>8VCRao0hZmIv5gVGFLqOD/7n6TQKlekA96U1QVzimKM=</P><Q>o1bchWA5ddDd59FED37QcrakoTXNoxRspFtsLDKEp1c=</Q><DP>ugF0VUE7wYNlkFP4VPoHjuTZNbRbhHn5uOmrRxqlvyk=</DP><DQ>XoGggC9Hr8pUyo9DIPAP7X+Ny5TU0Vm87m/TK9Ni+2s=</DQ><InverseQ>YqOHEP8dgCvz5Q8nhpQgdrKfdlmjkNAFxKF7j3pm09I=</InverseQ><D>mCpGy/rxS08e5iXn26LRQvvm5UfyLKMNZWmAGk2QF8cRGFB7dds/SI9wGTC9xyOoF4N2kWzYdLx+dYbR9lqwbQ==</D></RSAKeyValue>";
var publicKey = "<RSAKeyValue><Modulus>mfgthqgvK5P6kP00ojzA68+tGMwjEacduojFSukazKPXrZ8Q5XjzfqgJmDQ3wcWe3hWK92O3z/tmAuN47KA0ZQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
// 创建RSACryptoServiceProvider类的新实例
RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider(512);
RSAalg.PersistKeyInCsp = false;
RSAalg.FromXmlString(privateKey);
RSAParameters rsaParameters = RSAalg.ExportParameters(true);
String signedData = SignData(message, rsaParameters);
Console.WriteLine("signedData: " + signedData);
// 使用xml公钥进行验证
RSAalg.FromXmlString(publicKey);
rsaParameters = RSAalg.ExportParameters(false);
bool verifiedData = VerifyData(message, signedData, rsaParameters);
// 验证数据并将结果显示在控制台上。
if (VerifyData(message, signedData, rsaParameters)) {
Console.WriteLine("The data was verified.");
}
else {
Console.WriteLine("The data does not match the signature.");
}
}
catch(ArgumentNullException) {
Console.WriteLine("The data was not signed or verified");
}
}
static string SignData(string message, RSAParameters privateKey)
{
byte[] signedBytes;
using (var rsa = new RSACryptoServiceProvider())
{
var encoder = new UTF8Encoding();
byte[] originalData = encoder.GetBytes(message);
rsa.ImportParameters(privateKey);
signedBytes = rsa.SignData(originalData, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
rsa.PersistKeyInCsp = false;
}
return Convert.ToBase64String(signedBytes);
}
public static bool VerifyData(string message, string signedData, RSAParameters rsaParameters)
{
byte[] messageBytes;
byte[] signedBytes;
using (var rsa = new RSACryptoServiceProvider())
try
{
var encoder = new UTF8Encoding();
messageBytes = encoder.GetBytes(message);
signedBytes = Convert.FromBase64String(signedData);
rsa.ImportParameters(rsaParameters);
return rsa.VerifyData(messageBytes, new SHA1CryptoServiceProvider(), signedBytes);
}
catch(CryptographicException e) {
Console.WriteLine(e.Message);
return false;
}
}
}
Java-code:
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class MainSha1 {
public static void main(String[] args) throws GeneralSecurityException {
System.out.println("Should I use MessageDigest to verify a digital signature that signed in C#?");
String message = "this is the important message to sign";
// 这是一个示例和不安全的RSA 512位密钥
String publicKeyPem = "-----BEGIN PUBLIC KEY-----\n" +
"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJn4LYaoLyuT+pD9NKI8wOvPrRjMIxGn\n" +
"HbqIxUrpGsyj162fEOV4836oCZg0N8HFnt4Vivdjt8/7ZgLjeOygNGUCAwEAAQ==\n" +
"-----END PUBLIC KEY-----";
String signedData = "HS4qvrXpqu97me7yDt9lWXp+QLjKMO8FY4kiUiGhMhi6KmXQXCtmcUWSbg0i+LXv7u5ueRiQNeBnu6UCbPhZLg==";
String rsaInstanceString = "SHA1withRSA";
System.out.println("RSA instance: " + rsaInstanceString);
PublicKey publicKey = getPublicKeyFromString(publicKeyPem);
boolean verifyData = verifyRsa(publicKey, rsaInstanceString, message.getBytes(StandardCharsets.UTF_8), Base64.getDecoder().decode(signedData));
if (verifyData == true) {
System.out.println("The data was verified.");
} else {
System.out.println("The data could NOT get verified.");
}
}
public static PublicKey getPublicKeyFromString(String key) throws GeneralSecurityException {
String publicKeyPEM = key;
publicKeyPEM = publicKeyPEM.replace("-----BEGIN PUBLIC KEY-----", "");
publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----", "");
publicKeyPEM = publicKeyPEM.replaceAll("[\\r\\n]+", "");
byte[] encoded = Base64.get
<details>
<summary>英文:</summary>
The signature verification on Java-side has to fail as you are using different hashing algorithms on both sides.
In C# you are using SHA1 ('HashAlgorithmName.SHA1') and the Java-part is using SHA512 ('Signature signature = Signature.getInstance("Sha512withRSA");').
The following code is using SHA1 as hash algorithm but you can easily change this (on all codelines :-) to SHA256 or SHA512.
The C#-code verifies the signature with the public key, the same public key (encoded as PEM) is used in the Java-code
for verification only.
**Security warning: My example codes are using UNSECURE 512-bit RSA-keys that should not used in production.
There is not proper exception handling and you are using the padding 'RSASignaturePadding.Pkcs1' which should
NOT used anymore as well.**
This is the output of my C#-code:
Should I use MessageDigest to verify a digital signature that signed in C#?
signedData: mU2bcCMEhG13xG9sKwhaA//dnw2+rbLkwz2737cNU5kb2EBenJIEJ+bA596XccCVKUKPanxMUFoVw2fl8HhCNw==
The data was verified.
That's the Java-output:
RSA instance: SHA1withRSA
The data was verified.
C#-code:
using System;
using System.Security.Cryptography;
using System.Text;
class RSACSPSample {
static void Main() {
try {
Console.WriteLine("Should I use MessageDigest to verify a digital signature that signed in C#?");
// Create a UnicodeEncoder to convert between byte array and string.
ASCIIEncoding ByteConverter = new ASCIIEncoding();
string message = "this is the important message to sign";
// get private and public key ### SAMPLE and UNSECURE 512 bit RSA keypair
var privateKey = "<RSAKeyValue><Modulus>mfgthqgvK5P6kP00ojzA68+tGMwjEacduojFSukazKPXrZ8Q5XjzfqgJmDQ3wcWe3hWK92O3z/tmAuN47KA0ZQ==</Modulus><Exponent>AQAB</Exponent><P>8VCRao0hZmIv5gVGFLqOD/7n6TQKlekA96U1QVzimKM=</P><Q>o1bchWA5ddDd59FED37QcrakoTXNoxRspFtsLDKEp1c=</Q><DP>ugF0VUE7wYNlkFP4VPoHjuTZNbRbhHn5uOmrRxqlvyk=</DP><DQ>XoGggC9Hr8pUyo9DIPAP7X+Ny5TU0Vm87m/TK9Ni+2s=</DQ><InverseQ>YqOHEP8dgCvz5Q8nhpQgdrKfdlmjkNAFxKF7j3pm09I=</InverseQ><D>mCpGy/rxS08e5iXn26LRQvvm5UfyLKMNZWmAGk2QF8cRGFB7dds/SI9wGTC9xyOoF4N2kWzYdLx+dYbR9lqwbQ==</D></RSAKeyValue>";
var publicKey = "<RSAKeyValue><Modulus>mfgthqgvK5P6kP00ojzA68+tGMwjEacduojFSukazKPXrZ8Q5XjzfqgJmDQ3wcWe3hWK92O3z/tmAuN47KA0ZQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
// Create a new instance of the RSACryptoServiceProvider class
RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider(512);
RSAalg.PersistKeyInCsp = false;
RSAalg.FromXmlString(privateKey);
RSAParameters rsaParameters = RSAalg.ExportParameters(true);
String signedData = SignData(message, rsaParameters);
Console.WriteLine("signedData: " + signedData);
// verify with xml-public key
RSAalg.FromXmlString(publicKey);
rsaParameters = RSAalg.ExportParameters(false);
bool verifiedData = VerifyData(message, signedData, rsaParameters);
// Verify the data and display the result to the
// console.
if (VerifyData(message, signedData, rsaParameters)) {
Console.WriteLine("The data was verified.");
}
else {
Console.WriteLine("The data does not match the signature.");
}
}
catch(ArgumentNullException) {
Console.WriteLine("The data was not signed or verified");
}
}
static string SignData(string message, RSAParameters privateKey)
{
byte[] signedBytes;
using (var rsa = new RSACryptoServiceProvider())
{
var encoder = new UTF8Encoding();
byte[] originalData = encoder.GetBytes(message);
rsa.ImportParameters(privateKey);
signedBytes = rsa.SignData(originalData, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
rsa.PersistKeyInCsp = false;
}
return Convert.ToBase64String(signedBytes);
}
public static bool VerifyData(string message, string signedData, RSAParameters rsaParameters)
{
byte[] messageBytes;
byte[] signedBytes;
using (var rsa = new RSACryptoServiceProvider())
try
{
var encoder = new UTF8Encoding();
messageBytes = encoder.GetBytes(message);
signedBytes = Convert.FromBase64String(signedData);
rsa.ImportParameters(rsaParameters);
return rsa.VerifyData(messageBytes, new SHA1CryptoServiceProvider(), signedBytes);
}
catch(CryptographicException e) {
Console.WriteLine(e.Message);
return false;
}
}
}
Java-code:
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class MainSha1 {
public static void main(String[] args) throws GeneralSecurityException {
System.out.println("Should I use MessageDigest to verify a digital signature that signed in C#?");
String message = "this is the important message to sign";
// this is a SAMPLE and UNSECURE RSA 512 bit key
String publicKeyPem = "-----BEGIN PUBLIC KEY-----\n" +
"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJn4LYaoLyuT+pD9NKI8wOvPrRjMIxGn\n" +
"HbqIxUrpGsyj162fEOV4836oCZg0N8HFnt4Vivdjt8/7ZgLjeOygNGUCAwEAAQ==\n" +
"-----END PUBLIC KEY-----";
String signedData = "HS4qvrXpqu97me7yDt9lWXp+QLjKMO8FY4kiUiGhMhi6KmXQXCtmcUWSbg0i+LXv7u5ueRiQNeBnu6UCbPhZLg==";
String rsaInstanceString = "SHA1withRSA";
System.out.println("RSA instance: " + rsaInstanceString);
PublicKey publicKey = getPublicKeyFromString(publicKeyPem);
boolean verifyData = verifyRsa(publicKey, rsaInstanceString, message.getBytes(StandardCharsets.UTF_8), Base64.getDecoder().decode(signedData));
if (verifyData = true) {
System.out.println("The data was verified.");
} else {
System.out.println("The data could NOT get verified.");
}
}
public static PublicKey getPublicKeyFromString(String key) throws GeneralSecurityException {
String publicKeyPEM = key;
publicKeyPEM = publicKeyPEM.replace("-----BEGIN PUBLIC KEY-----", "");
publicKeyPEM = publicKeyPEM.replace("-----END PUBLIC KEY-----", "");
publicKeyPEM = publicKeyPEM.replaceAll("[\\r\\n]+", "");
byte[] encoded = Base64.getDecoder().decode(publicKeyPEM);
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pubKey = (PublicKey) kf.generatePublic(new X509EncodedKeySpec(encoded));
return pubKey;
}
public static Boolean verifyRsa(PublicKey publicKey, String rsaInstanceString, byte[] messageByte,
byte[] signatureByte) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
Signature publicSignature = Signature.getInstance(rsaInstanceString);
publicSignature.initVerify(publicKey);
publicSignature.update(messageByte);
return publicSignature.verify(signatureByte);
}
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论