views:

1189

answers:

5

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  A: 

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.

Chad Birch
The C# part will be distributed around the world, the PHP part runs on my web server. This is a serial code verification system. To use MD5/SHA-1 I would need the C#-part to know the salt, which is not desirable (because they could then sign their own serial codes).
Vegard Larsen
I would suggest rewriting your question to explain your actual objective then, that's not "signing" as the word would normally be used.
Chad Birch
I think you've overcomplicating the problem anyway. If you're going to send the information to your webserver to be verified anyway, why does the C# side need to know anything about the "signing" (as you called it) at all? Have the C# send the "short string" and the serial number, have the PHP see if they check out.
Chad Birch
Signing and hashing provide different functionality. Hashing verifies data integrity, while signing gets you data origin verification and non-repudiation. If he wants to verify data integrity (but has no idea where it's coming from) hashing is fine. If he wants to verify origin, he needs to sign it. If you want both, you need to do both.
Bob Somers
A: 

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)

blowdart
SHA1 is deprecated? I realize people have been poking holes in MD5 lately (albeit very tiny holes), but I am not aware of any such problems with SHA1.
Bob Somers
See http://www.schneier.com/blog/archives/2005/02/cryptanalysis_o.htmlNIST has this to say; "After 2010, Federal agencies may use SHA-1 only for the following applications: hash-based message authentication codes (HMACs); key derivation functions (KDFs); and random number generators (RNGs). Regardless of use, NIST encourages application and protocol designers to use the SHA-2 family of hash functions for all new applications and protocols."
blowdart
Yes, SHA-1 is deprecated. SHA-1 collisions can now be found in 2^63 operations - not 2^80 as expected by the initial research - http://www.rsa.com/rsalabs/node.asp?id=2927.
Will Bickford
A: 

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.

Bob Somers
+1  A: 

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();
diadiora
+1  A: 

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!");
}
russau