1 module hunt.security.x509.X509CRLEntry; 2 3 import hunt.security.x500.X500Principal; 4 5 import hunt.security.cert.CRLReason; 6 import hunt.security.x509.X509Extension; 7 import hunt.security.util.DerValue; 8 9 import hunt.Exceptions; 10 11 import hunt.collection.Set; 12 13 import std.bigint; 14 import std.datetime; 15 16 alias BigInteger = BigInt; 17 18 /** 19 * <p>Abstract class for a revoked certificate in a CRL (Certificate 20 * Revocation List). 21 * 22 * The ASN.1 definition for <em>revokedCertificates</em> is: 23 * <pre> 24 * revokedCertificates SEQUENCE OF SEQUENCE { 25 * userCertificate CertificateSerialNumber, 26 * revocationDate ChoiceOfTime, 27 * crlEntryExtensions Extensions OPTIONAL 28 * -- if present, must be v2 29 * } OPTIONAL 30 * 31 * CertificateSerialNumber ::= INTEGER 32 * 33 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension 34 * 35 * Extension ::= SEQUENCE { 36 * extnId OBJECT IDENTIFIER, 37 * critical BOOLEAN DEFAULT FALSE, 38 * extnValue OCTET STRING 39 * -- contains a DER encoding of a value 40 * -- of the type registered for use with 41 * -- the extnId object identifier value 42 * } 43 * </pre> 44 * 45 * @see X509CRL 46 * @see X509Extension 47 * 48 * @author Hemma Prafullchandra 49 */ 50 51 abstract class X509CRLEntry : X509Extension { 52 53 /** 54 * Compares this CRL entry for equality with the given 55 * object. If the {@code other} object is an 56 * {@code instanceof} {@code X509CRLEntry}, then 57 * its encoded form (the inner SEQUENCE) is retrieved and compared 58 * with the encoded form of this CRL entry. 59 * 60 * @param other the object to test for equality with this CRL entry. 61 * @return true iff the encoded forms of the two CRL entries 62 * match, false otherwise. 63 */ 64 override bool opEquals(Object other) { 65 if (this is other) 66 return true; 67 X509CRLEntry entry = cast(X509CRLEntry)other; 68 if (entry is null) 69 return false; 70 try { 71 byte[] thisCRLEntry = this.getEncoded(); 72 byte[] otherCRLEntry = entry.getEncoded(); 73 74 if (thisCRLEntry.length != otherCRLEntry.length) 75 return false; 76 for (int i = 0; i < thisCRLEntry.length; i++) 77 if (thisCRLEntry[i] != otherCRLEntry[i]) 78 return false; 79 } catch (CRLException ce) { 80 return false; 81 } 82 return true; 83 } 84 85 /** 86 * Returns a hashcode value for this CRL entry from its 87 * encoded form. 88 * 89 * @return the hashcode value. 90 */ 91 override size_t toHash() @trusted nothrow { 92 size_t retval = 0; 93 try { 94 byte[] entryData = this.getEncoded(); 95 for (size_t i = 1; i < entryData.length; i++) 96 retval += entryData[i] * i; 97 98 } catch (Exception ce) { 99 return(retval); 100 } 101 return(retval); 102 } 103 104 /** 105 * Returns the ASN.1 DER-encoded form of this CRL Entry, 106 * that is the inner SEQUENCE. 107 * 108 * @return the encoded form of this certificate 109 * @exception CRLException if an encoding error occurs. 110 */ 111 abstract byte[] getEncoded(); 112 113 /** 114 * Gets the serial number from this X509CRLEntry, 115 * the <em>userCertificate</em>. 116 * 117 * @return the serial number. 118 */ 119 abstract BigInteger getSerialNumber(); 120 121 /** 122 * Get the issuer of the X509Certificate described by this entry. If 123 * the certificate issuer is also the CRL issuer, this method returns 124 * null. 125 * 126 * <p>This method is used with indirect CRLs. The default implementation 127 * always returns null. Subclasses that wish to support indirect CRLs 128 * should override it. 129 * 130 * @return the issuer of the X509Certificate described by this entry 131 * or null if it is issued by the CRL issuer. 132 * 133 * @since 1.5 134 */ 135 X500Principal getCertificateIssuer() { 136 return null; 137 } 138 139 /** 140 * Gets the revocation date from this X509CRLEntry, 141 * the <em>revocationDate</em>. 142 * 143 * @return the revocation date. 144 */ 145 abstract Date getRevocationDate(); 146 147 /** 148 * Returns true if this CRL entry has extensions. 149 * 150 * @return true if this entry has extensions, false otherwise. 151 */ 152 abstract bool hasExtensions(); 153 154 /** 155 * Returns a string representation of this CRL entry. 156 * 157 * @return a string representation of this CRL entry. 158 */ 159 // abstract string toString(); 160 161 /** 162 * Returns the reason the certificate has been revoked, as specified 163 * in the Reason Code extension of this CRL entry. 164 * 165 * @return the reason the certificate has been revoked, or 166 * {@code null} if this CRL entry does not have 167 * a Reason Code extension 168 * @since 1.7 169 */ 170 CRLReason getRevocationReason() { 171 if (!hasExtensions()) { 172 return CRLReason.UNSPECIFIED; 173 } 174 return getRevocationReason(this); 175 } 176 177 178 /** 179 * This static method is the default implementation of the 180 * getRevocationReason method in X509CRLEntry. 181 */ 182 static CRLReason getRevocationReason(X509CRLEntry crlEntry) { 183 try { 184 byte[] ext = crlEntry.getExtensionValue("2.5.29.21"); 185 if (ext is null) { 186 return CRLReason.UNSPECIFIED; 187 } 188 DerValue val = new DerValue(ext); 189 byte[] data = val.getOctetString(); 190 191 // CRLReasonCodeExtension rcExt = 192 // new CRLReasonCodeExtension(false, data); 193 // return rcExt.getReasonCode(); 194 implementationMissing(); 195 return CRLReason.UNSPECIFIED; 196 } catch (IOException ioe) { 197 return CRLReason.UNSPECIFIED; 198 } 199 } 200 } 201