1 package org.bouncycastle.asn1.x509; 2 3 import org.bouncycastle.asn1.ASN1Object; 4 import org.bouncycastle.asn1.ASN1OctetString; 5 import org.bouncycastle.asn1.ASN1Primitive; 6 import org.bouncycastle.asn1.ASN1TaggedObject; 7 import org.bouncycastle.asn1.DEROctetString; 8 import org.bouncycastle.crypto.Digest; 9 // BEGIN android-changed 10 import org.bouncycastle.crypto.digests.AndroidDigestFactory; 11 // END android-changed 12 13 /** 14 * The SubjectKeyIdentifier object. 15 * <pre> 16 * SubjectKeyIdentifier::= OCTET STRING 17 * </pre> 18 */ 19 public class SubjectKeyIdentifier 20 extends ASN1Object 21 { 22 private byte[] keyidentifier; 23 24 public static SubjectKeyIdentifier getInstance( 25 ASN1TaggedObject obj, 26 boolean explicit) 27 { 28 return getInstance(ASN1OctetString.getInstance(obj, explicit)); 29 } 30 31 public static SubjectKeyIdentifier getInstance( 32 Object obj) 33 { 34 if (obj instanceof SubjectKeyIdentifier) 35 { 36 return (SubjectKeyIdentifier)obj; 37 } 38 else if (obj != null) 39 { 40 return new SubjectKeyIdentifier(ASN1OctetString.getInstance(obj)); 41 } 42 43 return null; 44 } 45 46 public static SubjectKeyIdentifier fromExtensions(Extensions extensions) 47 { 48 return SubjectKeyIdentifier.getInstance(extensions.getExtensionParsedValue(Extension.subjectKeyIdentifier)); 49 } 50 51 public SubjectKeyIdentifier( 52 byte[] keyid) 53 { 54 this.keyidentifier = keyid; 55 } 56 57 protected SubjectKeyIdentifier( 58 ASN1OctetString keyid) 59 { 60 this.keyidentifier = keyid.getOctets(); 61 } 62 63 public byte[] getKeyIdentifier() 64 { 65 return keyidentifier; 66 } 67 68 public ASN1Primitive toASN1Primitive() 69 { 70 return new DEROctetString(keyidentifier); 71 } 72 73 74 /** 75 * Calculates the keyidentifier using a SHA1 hash over the BIT STRING 76 * from SubjectPublicKeyInfo as defined in RFC3280. 77 * 78 * @param spki the subject public key info. 79 * @deprecated 80 */ 81 public SubjectKeyIdentifier( 82 SubjectPublicKeyInfo spki) 83 { 84 this.keyidentifier = getDigest(spki); 85 } 86 87 /** 88 * Return a RFC 3280 type 1 key identifier. As in: 89 * <pre> 90 * (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the 91 * value of the BIT STRING subjectPublicKey (excluding the tag, 92 * length, and number of unused bits). 93 * </pre> 94 * @param keyInfo the key info object containing the subjectPublicKey field. 95 * @return the key identifier. 96 * @deprecated use org.bouncycastle.cert.X509ExtensionUtils.createSubjectKeyIdentifier 97 */ 98 public static SubjectKeyIdentifier createSHA1KeyIdentifier(SubjectPublicKeyInfo keyInfo) 99 { 100 return new SubjectKeyIdentifier(keyInfo); 101 } 102 103 /** 104 * Return a RFC 3280 type 2 key identifier. As in: 105 * <pre> 106 * (2) The keyIdentifier is composed of a four bit type field with 107 * the value 0100 followed by the least significant 60 bits of the 108 * SHA-1 hash of the value of the BIT STRING subjectPublicKey. 109 * </pre> 110 * @param keyInfo the key info object containing the subjectPublicKey field. 111 * @return the key identifier. 112 * @deprecated use org.bouncycastle.cert.X509ExtensionUtils.createTruncatedSubjectKeyIdentifier 113 */ 114 public static SubjectKeyIdentifier createTruncatedSHA1KeyIdentifier(SubjectPublicKeyInfo keyInfo) 115 { 116 byte[] dig = getDigest(keyInfo); 117 byte[] id = new byte[8]; 118 119 System.arraycopy(dig, dig.length - 8, id, 0, id.length); 120 121 id[0] &= 0x0f; 122 id[0] |= 0x40; 123 124 return new SubjectKeyIdentifier(id); 125 } 126 127 private static byte[] getDigest(SubjectPublicKeyInfo spki) 128 { 129 // BEGIN android-changed 130 Digest digest = AndroidDigestFactory.getSHA1(); 131 // END android-changed 132 byte[] resBuf = new byte[digest.getDigestSize()]; 133 134 byte[] bytes = spki.getPublicKeyData().getBytes(); 135 digest.update(bytes, 0, bytes.length); 136 digest.doFinal(resBuf, 0); 137 return resBuf; 138 } 139 } 140