Confused, how do I use a key and sign a document Symmetrically?
Im trying to work out how to do the below in c#.
Posted a couple of times about this seems very confusing. I have an xml document I want to be able to sign the document symmetrically and create a signature at the end.
First:
The signature needs to be created using
1) the data in the document 2) a unique key (a word or byte array that we create)
And then I need to write a program which will spit out a signature that we can ship with the document using the data and key above.
Second:
At the other end the custumer will run the program which has the unique key in it (the key in step 2) above), it will look at the signature that we shipped. And it will then be able to tell if the data was signed using that key. If the data has changed then the test will fail. This way we know the customer has not tampered with the xml file.
开发者_如何转开发NOTE: I undestand that this isnt very secure but is enough for now for us.
How is this done? just cant seem to get the basics of encryption :-)
you should have a look into MAC (message authentication codes) https://secure.wikimedia.org/wikipedia/en/wiki/Message_authentication_code
It is not necessarely unsecure. The problem is just that every one in possition of the key can create valid signatures. This means that everyone that has to be able to verfiy signatures can also create them and you can not determine who actually signed the data.
For "pretty good" security, I would recommend HMAC-SHA1 with a key that is at least 160 bits (20 bytes) long. For learning about more advanced cryptography, I highly recommend the classic Schneier book, Applied Cryptography.
To generate the HMAC, you can use the handy HMACSHA1 class.
For example:
/// Pass in the xml text to sign, along with a hex or Base64-encoded, 160-bit secret key
public string GenerateSignature(string xml, string secretKey)
{
using (HMACSHA1 encoder = new HMACSHA1(secretKey.ToAscii(), true))
{
return encoder.ComputeHash(xml.ToUtf8()).ToBase64();
}
}
...using these extension methods:
public static byte[] ToUtf8(this string str)
{
return Encoding.UTF8.GetBytes(str);
}
public static byte[] ToAscii(this string str)
{
return Encoding.ASCII.GetBytes(str);
}
public static string ToBase64(this byte[] bytes)
{
return Convert.ToBase64String(bytes);
}
To generate the secret key, you can go to random.org (not completely secure, but may be adequate for your needs), or do it programmatically like so:
System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
byte[] key = new byte[20];
rng.GetBytes(key);
string secretKey = key.ToBase64()
Here are some more extension methods you might find handy:
public static string ToHex(this byte[] bytes)
{
char[] c = new char[bytes.Length * 2];
byte b;
for(int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)
{
b = ((byte)(bytes[bx] >> 4));
c[cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);
b = ((byte)(bytes[bx] & 0x0F));
c[++cx]=(char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);
}
return new string(c);
}
public static byte[] HexToBytes(this string str)
{
if (str.Length == 0 || str.Length % 2 != 0)
return new byte[0];
byte[] buffer = new byte[str.Length / 2];
char c;
for (int bx = 0, sx = 0; bx < buffer.Length; ++bx, ++sx)
{
// Convert first half of byte
c = str[sx];
buffer[bx] = (byte)((c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0')) << 4);
// Convert second half of byte
c = str[++sx];
buffer[bx] |= (byte)(c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0'));
}
return buffer;
}
精彩评论