Digitally sign in PHP using private key, verify in

2019-05-18 07:41发布

问题:

I am working on a feature that needs me to digitally sign a short string in PHP, and verify the string's signature in C#.

I would really like to use openssl_sign in PHP, because of its simplicity, but all the information I can find on Google indicates that this will not work.

There are some external libraries that claim to do this well, however as this is a hobby project I would rather not purchase such a library.

So what are the alternatives here? Full interoperability between C# and PHP is required. Libraries besides OpenSSL can be used.

回答1:

I've done something very similar using Bouncy Castle Crypto APIs. It appears PHP openssl_sign uses SHA1 by default. If you are using anything other than the default you'll need to change the algorithm parameter for GetSigner.

string base64pubkey = "<!-- BASE64 representation of your pubkey from open ssl -->";
RsaKeyParameters pubKey = PublicKeyFactory.CreateKey(Convert.FromBase64String(base64pubkey)) as RsaKeyParameters;
byte[] signature = Convert.FromBase64String("<!-- BASE64 representation of your sig -->");
byte[] message = Encoding.ASCII.GetBytes("Something that has been signed");


ISigner sig = SignerUtilities.GetSigner("SHA1WithRSAEncryption");
sig.Init(false, pubKey);
sig.BlockUpdate(message, 0, message.Length);
if (sig.VerifySignature(signature))
{
    Console.WriteLine("all good!");
}


回答2:

You may use to check the digital signature smth like this:

string publicKey = "some key";
// Verifying Step 1: Create the digital signature algorithm object
DSACryptoServiceProvider verifier = new DSACryptoServiceProvider();

// Verifying Step 2: Import the signature and public key.
verifier.FromXmlString(publicKey);

// Verifying Step 3: Store the data to be verified in a byte array
FileStream file = new FileStream(args[0], FileMode.Open, FileAccess.Read);
BinaryReader reader = new BinaryReader(file2);
byte[] data = reader.ReadBytes((int)file2.Length);

// Verifying Step 4: Call the VerifyData method
if (verifier.VerifyData(data, signature))
    Console.WriteLine("Signature verified");
else
    Console.WriteLine("Signature NOT verified");
reader.Close();
file.Close();


回答3:

Is there a reason you need something as complex as SSL signing? Can't you just use a simple one-way hash like MD5/SHA-1 on the string? If all you're looking for is verification that the string wasn't tampered with, that should be sufficient.



回答4:

So looking at this - this guy appears to have asymmetric signing and encrypting working between PHP and C#. Signing should not be a problem, SHA* and MD* are standard, and so it's very very unlikely that is going to not be compatible (although you should be looking at SHA256 as MD* and SHA1 are deprecated due to vulnerabilities)



回答5:

We're missing some context as to why you need to sign it. You may not need to.

The important question is: what guarantees do you need from your data?

If all you need to do is verify the integrity of the data, a hash will do the job. If you need to verify where it's coming from, you need to sign it. If you need both, hash it, concatenate the payload with the hash, and sign the whole thing.

Regarding cross-platform libraries... you really should need to worry about it. A SHA1 is a SHA1 is a SHA1, no matter which library generated it. Same thing with generating and verifying digital signatures. Use what's easiest in PHP and use what's easiest in C#. If they're both set up correctly you shouldn't need to worry about it.