我应该使用MessageDigest来验证在C#中签名的数字签名吗?

huangapple go评论65阅读模式
英文:

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 (&#39;HashAlgorithmName.SHA1&#39;) and the Java-part is using SHA512 (&#39;Signature signature = Signature.getInstance(&quot;Sha512withRSA&quot;);&#39;).

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 &#39;RSASignaturePadding.Pkcs1&#39; 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&#39;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(&quot;Should I use MessageDigest to verify a digital signature that signed in C#?&quot;);
    			// Create a UnicodeEncoder to convert between byte array and string.
    			ASCIIEncoding ByteConverter = new ASCIIEncoding();
    
    			string message = &quot;this is the important message to sign&quot;;
    
    			// get private and public key ### SAMPLE and UNSECURE 512 bit RSA keypair
    			var privateKey = &quot;&lt;RSAKeyValue&gt;&lt;Modulus&gt;mfgthqgvK5P6kP00ojzA68+tGMwjEacduojFSukazKPXrZ8Q5XjzfqgJmDQ3wcWe3hWK92O3z/tmAuN47KA0ZQ==&lt;/Modulus&gt;&lt;Exponent&gt;AQAB&lt;/Exponent&gt;&lt;P&gt;8VCRao0hZmIv5gVGFLqOD/7n6TQKlekA96U1QVzimKM=&lt;/P&gt;&lt;Q&gt;o1bchWA5ddDd59FED37QcrakoTXNoxRspFtsLDKEp1c=&lt;/Q&gt;&lt;DP&gt;ugF0VUE7wYNlkFP4VPoHjuTZNbRbhHn5uOmrRxqlvyk=&lt;/DP&gt;&lt;DQ&gt;XoGggC9Hr8pUyo9DIPAP7X+Ny5TU0Vm87m/TK9Ni+2s=&lt;/DQ&gt;&lt;InverseQ&gt;YqOHEP8dgCvz5Q8nhpQgdrKfdlmjkNAFxKF7j3pm09I=&lt;/InverseQ&gt;&lt;D&gt;mCpGy/rxS08e5iXn26LRQvvm5UfyLKMNZWmAGk2QF8cRGFB7dds/SI9wGTC9xyOoF4N2kWzYdLx+dYbR9lqwbQ==&lt;/D&gt;&lt;/RSAKeyValue&gt;&quot;;
    			var publicKey = &quot;&lt;RSAKeyValue&gt;&lt;Modulus&gt;mfgthqgvK5P6kP00ojzA68+tGMwjEacduojFSukazKPXrZ8Q5XjzfqgJmDQ3wcWe3hWK92O3z/tmAuN47KA0ZQ==&lt;/Modulus&gt;&lt;Exponent&gt;AQAB&lt;/Exponent&gt;&lt;/RSAKeyValue&gt;&quot;;
    			
    			// 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(&quot;signedData: &quot; + 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(&quot;The data was verified.&quot;);
    			}
    			else {
    				Console.WriteLine(&quot;The data does not match the signature.&quot;);
    			}
    		}
    		catch(ArgumentNullException) {
    			Console.WriteLine(&quot;The data was not signed or verified&quot;);
    		}
    	}
    	
    	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(&quot;Should I use MessageDigest to verify a digital signature that signed in C#?&quot;);
            String message = &quot;this is the important message to sign&quot;;
            // this is a SAMPLE and UNSECURE RSA 512 bit key
            String publicKeyPem = &quot;-----BEGIN PUBLIC KEY-----\n&quot; +
                    &quot;MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJn4LYaoLyuT+pD9NKI8wOvPrRjMIxGn\n&quot; +
                    &quot;HbqIxUrpGsyj162fEOV4836oCZg0N8HFnt4Vivdjt8/7ZgLjeOygNGUCAwEAAQ==\n&quot; +
                    &quot;-----END PUBLIC KEY-----&quot;;
            String signedData = &quot;HS4qvrXpqu97me7yDt9lWXp+QLjKMO8FY4kiUiGhMhi6KmXQXCtmcUWSbg0i+LXv7u5ueRiQNeBnu6UCbPhZLg==&quot;;
            String rsaInstanceString = &quot;SHA1withRSA&quot;;
            System.out.println(&quot;RSA instance: &quot; + 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(&quot;The data was verified.&quot;);
            } else {
                System.out.println(&quot;The data could NOT get verified.&quot;);
            }
    
        }
    
        public static PublicKey getPublicKeyFromString(String key) throws GeneralSecurityException {
            String publicKeyPEM = key;
            publicKeyPEM = publicKeyPEM.replace(&quot;-----BEGIN PUBLIC KEY-----&quot;, &quot;&quot;);
            publicKeyPEM = publicKeyPEM.replace(&quot;-----END PUBLIC KEY-----&quot;, &quot;&quot;);
            publicKeyPEM = publicKeyPEM.replaceAll(&quot;[\\r\\n]+&quot;, &quot;&quot;);
            byte[] encoded = Base64.getDecoder().decode(publicKeyPEM);
            KeyFactory kf = KeyFactory.getInstance(&quot;RSA&quot;);
            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>



huangapple
  • 本文由 发表于 2020年8月27日 20:25:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/63615966.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定