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

Java 我应该使用MessageDigest验证在C#中签名的数字签名吗?,java,c#,rsa,digital-signature,Java,C#,Rsa,Digital Signature,我是Java新手,想用c#对一些数据进行签名,并用RSA和SHA512在Java中进行验证 C#: 爪哇: 我使用RSA以及公钥和私钥。Java函数总是返回false,没有错误或异常。 如果我像下面这样删除MessageDigest,它就会开始工作,它是否安全 static boolean verifySignature512(String message, String sign, PublicKey publicKey) throws Exception { // MessageDig

我是Java新手,想用c#对一些数据进行签名,并用RSA和SHA512在Java中进行验证

C#:

爪哇:

我使用RSA以及公钥和私钥。Java函数总是返回false,没有错误或异常。 如果我像下面这样删除MessageDigest,它就会开始工作,它是否安全

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

Java端的签名验证必须失败,因为双方都使用不同的哈希算法。 在C语言中,您使用的是SHA1('HashAlgorithmName.SHA1'),Java部分使用的是SHA512('Signature Signature=Signature.getInstance(“Sha512withRSA”);)

下面的代码使用SHA1作为哈希算法,但您可以轻松地将其(在所有代码行上:-)更改为SHA256或SHA512。 C代码用公钥验证签名,Java代码中使用相同的公钥(编码为PEM) 仅供核实

安全警告:我的示例代码使用的是不安全的512位RSA密钥,不应在生产中使用。 没有正确的异常处理,您正在使用填充“rsAssignaturePadding.Pkcs1”,它应该 也不再使用。

这是我的C#代码的输出:

这就是Java输出:

RSA instance: SHA1withRSA
The data was verified.
C#-代码:

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));
}
Should I use MessageDigest to verify a digital signature that signed in C#?
signedData: mU2bcCMEhG13xG9sKwhaA//dnw2+rbLkwz2737cNU5kb2EBenJIEJ+bA596XccCVKUKPanxMUFoVw2fl8HhCNw==
The data was verified.
RSA instance: SHA1withRSA
The data was verified.
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;
        }
    }
}
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);
    }
}