private int version;
private byte[] serialnumber;
-// private byte[] issuerUniqueID;
-// private byte[] subjectUniqueID;
+ private byte[] issuerUniqueID;
+ private byte[] subjectUniqueID;
private X509ExtensionCollection extensions;
-#if NET_2_0
- private const bool reversed = true;
-#else
- private const bool reversed = false;
-#endif
+ private static string encoding_error = Locale.GetText ("Input data cannot be coded as a valid certificate.");
+
// that's were the real job is!
private void Parse (byte[] data)
{
- string e = "Input data cannot be coded as a valid certificate.";
try {
decoder = new ASN1 (data);
// Certificate
if (decoder.Tag != 0x30)
- throw new CryptographicException (e);
+ throw new CryptographicException (encoding_error);
// Certificate / TBSCertificate
if (decoder [0].Tag != 0x30)
- throw new CryptographicException (e);
+ throw new CryptographicException (encoding_error);
ASN1 tbsCertificate = decoder [0];
// Certificate / TBSCertificate / CertificateSerialNumber
ASN1 sn = decoder [0][tbs++];
if (sn.Tag != 0x02)
- throw new CryptographicException (e);
+ throw new CryptographicException (encoding_error);
serialnumber = sn.Value;
Array.Reverse (serialnumber, 0, serialnumber.Length);
m_signaturealgoparams = null;
// Certificate / TBSCertificate / issuerUniqueID
- ASN1 issuerUID = tbsCertificate.Element (tbs, 0xA1);
+ ASN1 issuerUID = tbsCertificate.Element (tbs, 0x81);
if (issuerUID != null) {
tbs++;
-// issuerUniqueID = issuerUID.Value;
+ issuerUniqueID = issuerUID.Value;
}
// Certificate / TBSCertificate / subjectUniqueID
- ASN1 subjectUID = tbsCertificate.Element (tbs, 0xA2);
+ ASN1 subjectUID = tbsCertificate.Element (tbs, 0x82);
if (subjectUID != null) {
tbs++;
-// subjectUniqueID = subjectUID.Value;
+ subjectUniqueID = subjectUID.Value;
}
// Certificate / TBSCertificate / Extensions
m_encodedcert = (byte[]) data.Clone ();
}
catch (Exception ex) {
- throw new CryptographicException (e, ex);
+ throw new CryptographicException (encoding_error, ex);
}
}
public X509Certificate (byte[] data)
{
- if (data != null)
+ if (data != null) {
+ // does it looks like PEM ?
+ if ((data.Length > 0) && (data [0] == 0x2D)) {
+ try {
+ data = PEM ("CERTIFICATE", data);
+ }
+ catch (Exception ex) {
+ throw new CryptographicException (encoding_error, ex);
+ }
+ }
Parse (data);
+ }
}
private byte[] GetUnsignedBigInteger (byte[] integer)
public DSA DSA {
get {
+ if (m_keyalgoparams == null)
+ throw new CryptographicException ("Missing key algorithm parameters.");
+
if (_dsa == null) {
DSAParameters dsaParams = new DSAParameters ();
// for DSA m_publickey contains 1 ASN.1 integer - Y
return null;
return (byte[]) m_keyalgoparams.Clone ();
}
+ set { m_keyalgoparams = value; }
}
public virtual byte[] PublicKey {
ASN1 sign = new ASN1 (signature);
if ((sign == null) || (sign.Count != 2))
return null;
- // parts may be less than 20 bytes (i.e. first bytes were 0x00)
byte[] part1 = sign [0].Value;
byte[] part2 = sign [1].Value;
byte[] sig = new byte [40];
- Buffer.BlockCopy (part1, 0, sig, (20 - part1.Length), part1.Length);
- Buffer.BlockCopy (part2, 0, sig, (40 - part2.Length), part2.Length);
+ // parts may be less than 20 bytes (i.e. first bytes were 0x00)
+ // parts may be more than 20 bytes (i.e. first byte > 0x80, negative)
+ int s1 = System.Math.Max (0, part1.Length - 20);
+ int e1 = System.Math.Max (0, 20 - part1.Length);
+ Buffer.BlockCopy (part1, s1, sig, e1, part1.Length - s1);
+ int s2 = System.Math.Max (0, part2.Length - 20);
+ int e2 = System.Math.Max (20, 40 - part2.Length);
+ Buffer.BlockCopy (part2, s2, sig, e2, part2.Length - s2);
return sig;
default:
return ((instant > ValidFrom) && (instant <= ValidUntil));
}
+ // uncommon v2 "extension"
+ public byte[] IssuerUniqueIdentifier {
+ get {
+ if (issuerUniqueID == null)
+ return null;
+ return (byte[]) issuerUniqueID.Clone ();
+ }
+ }
+
+ // uncommon v2 "extension"
+ public byte[] SubjectUniqueIdentifier {
+ get {
+ if (subjectUniqueID == null)
+ return null;
+ return (byte[]) subjectUniqueID.Clone ();
+ }
+ }
+
internal bool VerifySignature (DSA dsa)
{
// signatureOID is check by both this.Hash and this.Signature
// note: we NEVER serialize the private key
}
#endif
+
+ static byte[] PEM (string type, byte[] data)
+ {
+ string pem = Encoding.ASCII.GetString (data);
+ string header = String.Format ("-----BEGIN {0}-----", type);
+ string footer = String.Format ("-----END {0}-----", type);
+ int start = pem.IndexOf (header) + header.Length;
+ int end = pem.IndexOf (footer, start);
+ string base64 = pem.Substring (start, (end - start));
+ return Convert.FromBase64String (base64);
+ }
}
}