private static byte[] DERDecodeSignature(byte[] data)
{
// In DSA the signature length is always 2*20 bytes
int sigLength = 20;
// This is the largest we can decode, check type
if (data.Length > 65538 || data[0] != 0x30) {
throw new Exception("Invalid signature");
}
int fullConsumed;
byte[] encoded = DERDecodeVector(data, 1, out fullConsumed);
if (encoded[0] != 0x02)
throw new Exception("Invalid signature");
int rConsumed;
byte[] R = DERDecodeVector(encoded, 1, out rConsumed);
if (encoded[1+rConsumed] != 0x02)
throw new Exception("Invalid signature");
int sConsumed;
byte[] S = DERDecodeVector(encoded, 1+rConsumed+1, out sConsumed);
if (1+rConsumed+1+sConsumed != encoded.Length)
throw new Exception("Invalid signature");
// Make sure the signature is valid
for (int i=0; i<R.Length-sigLength; i++) {
if (R[i] != 0)
throw new Exception("Invalid signature");
}
for (int i=0; i<S.Length-sigLength; i++) {
if (S[i] != 0)
throw new Exception("Invalid signature");
}
// Copy signature bytes to the decoded array
byte[] ret = new byte[sigLength*2];
Buffer.BlockCopy(R, System.Math.Max(0, R.Length-sigLength),
ret, System.Math.Max(0, sigLength-R.Length),
System.Math.Min(sigLength, R.Length));
Buffer.BlockCopy(S, System.Math.Max(0, S.Length-sigLength),
ret, sigLength+System.Math.Max(0, sigLength-S.Length),
System.Math.Min(sigLength, S.Length));
return ret;
}