1 module hunt.security.x509.KeyIdentifier; 2 3 import hunt.security.x509.AlgorithmId; 4 import hunt.security.util.DerValue; 5 import hunt.security.util.DerOutputStream; 6 7 import hunt.security.Key; 8 import hunt.Exceptions; 9 10 import std.format; 11 12 /** 13 * Represent the Key Identifier ASN.1 object. 14 * 15 * @author Amit Kapoor 16 * @author Hemma Prafullchandra 17 */ 18 class KeyIdentifier { 19 private byte[] octetString; 20 21 /** 22 * Create a KeyIdentifier with the passed bit settings. 23 * 24 * @param octetString the octet string identifying the key identifier. 25 */ 26 this(byte[] octetString) { 27 this.octetString = octetString.dup; 28 } 29 30 /** 31 * Create a KeyIdentifier from the DER encoded value. 32 * 33 * @param val the DerValue 34 */ 35 this(DerValue val) { 36 octetString = val.getOctetString(); 37 } 38 39 /** 40 * Creates a KeyIdentifier from a public-key value. 41 * 42 * <p>From RFC2459: Two common methods for generating key identifiers from 43 * the key are: 44 * <ol> 45 * <li>The keyIdentifier is composed of the 160-bit SHA-1 hash of the 46 * value of the BIT STRING subjectPublicKey (excluding the tag, 47 * length, and number of unused bits). 48 * <p> 49 * <li>The keyIdentifier is composed of a four bit type field with 50 * the value 0100 followed by the least significant 60 bits of the 51 * SHA-1 hash of the value of the BIT STRING subjectPublicKey. 52 * </ol> 53 * <p>This method supports method 1. 54 * 55 * @param pubKey the key from which to construct this KeyIdentifier 56 * @throws IOException on parsing errors 57 */ 58 this(PublicKey pubKey) 59 { 60 DerValue algAndKey = new DerValue(pubKey.getEncoded()); 61 if (algAndKey.tag != DerValue.tag_Sequence) 62 throw new IOException("PublicKey value is not a valid " 63 ~ "X.509 key"); 64 65 // AlgorithmId algid = AlgorithmId.parse(algAndKey.data.getDerValue()); 66 // byte[] key = algAndKey.data.getUnalignedBitString().toByteArray(); 67 68 // MessageDigest md = null; 69 // try { 70 // md = MessageDigest.getInstance("SHA1"); 71 // } catch (NoSuchAlgorithmException e3) { 72 // throw new IOException("SHA1 not supported"); 73 // } 74 // md.update(key); 75 // this.octetString = md.digest(); 76 implementationMissing(); 77 } 78 79 /** 80 * Return the value of the KeyIdentifier as byte array. 81 */ 82 byte[] getIdentifier() { 83 return octetString.dup; 84 } 85 86 /** 87 * Returns a printable representation of the KeyUsage. 88 */ 89 override string toString() { 90 // string s = "KeyIdentifier [\n"; 91 92 // HexDumpEncoder encoder = new HexDumpEncoder(); 93 // s += encoder.encodeBuffer(octetString); 94 // s += "]\n"; 95 string s = format("KeyIdentifier [\n%(%02X%)]\n", octetString); 96 return (s); 97 } 98 99 /** 100 * Write the KeyIdentifier to the DerOutputStream. 101 * 102 * @param stream the DerOutputStream to write the object to. 103 * @exception IOException 104 */ 105 void encode(DerOutputStream stream) { 106 stream.putOctetString(octetString); 107 } 108 109 /** 110 * Returns a hash code value for this object. 111 * Objects that are equal will also have the same hashcode. 112 */ 113 override size_t toHash() @trusted const nothrow { 114 size_t retval = 0; 115 for (size_t i = 0; i < octetString.length; i++) 116 retval += octetString[i] * i; 117 return retval; 118 } 119 120 /** 121 * Indicates whether some other object is "equal to" this one. 122 */ 123 override bool opEquals(Object other) { 124 if (this is other) 125 return true; 126 KeyIdentifier id = cast(KeyIdentifier)other; 127 if(id is null) 128 return false; 129 byte[] otherString = id.octetString; 130 return octetString == otherString; 131 } 132 }