0

I have a signature generator in Java:

private static String getPvtKeyFromConfig = "merchantPvtKey";
private static String getPubKeyFromConfig = "merchantPubKey";
private static String getSaltFromConfig = "merchant_salt";
public  static void main(String[] args) throws Exception {   
    // Generate Signature    
    String uniqueId="ab123";
    byte[] data = Base64.decodeBase64(uniqueId);
    java.security.Signature sig =java.security.Signature.getInstance("SHA1WithRSA");        
    sig.initSign(getPrivateFromSpec(getPvtKeyFromConfig));
    sig.update(data);  
    byte[] signatureBytes = sig.sign(); 
    System.out.println("Signature for uniqueId - "+uniqueId+": "+ Base64.encodeBase64String(signatureBytes));
}

How can I do it in C#?

Lauren Rutledge
  • 1,195
  • 5
  • 18
  • 27
  • This is too similar to [this question](https://stackoverflow.com/questions/7444586/how-can-i-sign-a-file-using-rsa-and-sha256-with-net) you could check it – Cleptus Oct 04 '18 at 14:30
  • Libraries...As for the base 64, look at Convert.ToBase64String and Convert.FromBase64String. – Ross Bush Oct 04 '18 at 14:53
  • I'm not convinced "here's some java code" counts as attempting to solve this problem yourself first – Liam Oct 04 '18 at 15:26
  • Possible duplicate of [Java Digital Signature different to C#](https://stackoverflow.com/questions/17338034/java-digital-signature-different-to-c-sharp) – Liam Oct 04 '18 at 15:27
  • Possible duplicate of [Using AsymmetricAlgorithm Private and Public key with RSA C#](https://stackoverflow.com/questions/3206660/using-asymmetricalgorithm-private-and-public-key-with-rsa-c-sharp) – JuanR Oct 04 '18 at 16:03

2 Answers2

1

I think this is what you are looking for:

static byte[] Sign(string text, string certSubject)
{
    // Access a store
    using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
    {
        store.Open(OpenFlags.ReadOnly);

        // Find the certificate used to sign
        RSACryptoServiceProvider provider = null;
        foreach (X509Certificate2 cert in store.Certificates)
        {
            if (cert.Subject.Contains(certSubject))
            {
                // Get its associated CSP and private key
                provider = (RSACryptoServiceProvider)cert.PrivateKey;
                break;
            }
        }

        if (provider == null)
            throw new Exception("Certificate not found.");

        // Hash the data
        var hash = HashText(text);

        // Sign the hash
        var signature = provider.SignHash(hash, CryptoConfig.MapNameToOID("SHA1"));
        return signature;
    }                
}


static bool Verify(string text, byte[] signature, string certPath)
{

    // Load the certificate used to verify the signature
    X509Certificate2 certificate = new X509Certificate2(certPath);

    // Get its associated provider and public key
    RSACryptoServiceProvider provider = (RSACryptoServiceProvider)certificate.PublicKey.Key;

    // Hash the data
    var hash = HashText(text);

    // Verify the signature with the hash
    var result = provider.VerifyHash(hash, CryptoConfig.MapNameToOID("SHA1"), signature);
    return result;
}

static byte[] HashText(string text)
{
    SHA1Managed sha1Hasher = new SHA1Managed();
    UnicodeEncoding encoding = new UnicodeEncoding();
    byte[] data = encoding.GetBytes(text);
    byte[] hash = sha1Hasher.ComputeHash(data);
    return hash;
}

Sample usage:

var signature = Sign("To be or not to be, that is the question.", "CN=some_cert");
var result = Verify("To be or not to be, that is the question.", signature, "C:\\temp\\some_cert.cer");
Console.WriteLine("Verified: {0}", result);
JuanR
  • 7,405
  • 1
  • 19
  • 30
  • Thanks...But I have no any certificate, I have just ready public and private key in XML format. – Oleh Yavorskiy Oct 04 '18 at 15:59
  • @OlehYavorskiy: You did not mention this in your original question. – JuanR Oct 04 '18 at 16:02
  • I am sorry... can I do it anyway with XML keys? – Oleh Yavorskiy Oct 04 '18 at 16:18
  • @OlehYavorskiy: It's OK. Welcome to SO. See the comment added when I marked the question as a duplicate. There is a link to another question that may help you. Good luck! – JuanR Oct 04 '18 at 17:45
  • @JuanR Hi! someone know what it's "CN=some_cert" –  Jun 19 '19 at 16:43
  • Hi @Vulpex. It's the certificate's subject which is used to lookup the certificate in the store. Read more about it here: https://tools.ietf.org/html/rfc5280#section-4.1.2.6 – JuanR Jun 19 '19 at 17:26
0

Below C# code works for me for the exact java code mentioned in the question. Few Notes : .) Your project should have Target frameworks as 4.8 .) You should have existing private key .) Using this Private key we can generate the .pfx certificate by using the OpenSSL commands.( we will have to generate the .crt first and then .pfx)

static string GenerateSignatureUsingCert(string dataToSign)
        {
            X509Certificate2 certificate = new X509Certificate2(@"C:\PFX\MyCertificate.pfx", "****", X509KeyStorageFlags.Exportable);
            RSA privateKey1 = certificate.GetRSAPrivateKey();
            

            Encoding unicode = Encoding.UTF8;
            byte[] bytesInUni = unicode.GetBytes(dataToSign);
            
            return Convert.ToBase64String(privateKey1.SignData(bytesInUni, HashAlgorithmName.SHA256,RSASignaturePadding.Pkcs1));
        }

Usage

string canonicalizeData = CanonicalizeHeaders(headers); 

            String data = null;
            try
            {
                data = GenerateSignatureUsingCert(canonicalizeData);               
            }
            catch(Exception ex) 
            {
                Console.WriteLine(ex.Message);
            }
          Console.WriteLine("Signature: " + data);
Pramod Nikumbh
  • 3,729
  • 1
  • 11
  • 3