1e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrompackage org.bouncycastle.cert.selector;
2e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
3e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport java.math.BigInteger;
4e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
5e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.ASN1OctetString;
6e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
7e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.x500.X500Name;
8e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.asn1.x509.Extension;
9e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.cert.X509CertificateHolder;
10e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.util.Arrays;
11e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstromimport org.bouncycastle.util.Selector;
12e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
13e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom/**
14e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom * a basic index for a X509CertificateHolder class
15e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom */
16e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrompublic class X509CertificateHolderSelector
17e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    implements Selector
18e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom{
19e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private byte[] subjectKeyId;
20e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
21e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private X500Name issuer;
22e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private BigInteger serialNumber;
23e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
24e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
25e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * Construct a selector with the value of a public key's subjectKeyId.
26e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     *
27e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @param subjectKeyId a subjectKeyId
28e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
29e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public X509CertificateHolderSelector(byte[] subjectKeyId)
30e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
31e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this(null, null, subjectKeyId);
32e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
33e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
34e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
35e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * Construct a signer ID based on the issuer and serial number of the signer's associated
36e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * certificate.
37e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     *
38e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @param issuer the issuer of the signer's associated certificate.
39e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @param serialNumber the serial number of the signer's associated certificate.
40e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
41e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public X509CertificateHolderSelector(X500Name issuer, BigInteger serialNumber)
42e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
43e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this(issuer, serialNumber, null);
44e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
45e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
46e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    /**
47e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * Construct a signer ID based on the issuer and serial number of the signer's associated
48e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * certificate.
49e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     *
50e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @param issuer the issuer of the signer's associated certificate.
51e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @param serialNumber the serial number of the signer's associated certificate.
52e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     * @param subjectKeyId the subject key identifier to use to match the signers associated certificate.
53e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom     */
54e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public X509CertificateHolderSelector(X500Name issuer, BigInteger serialNumber, byte[] subjectKeyId)
55e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
56e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this.issuer = issuer;
57e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this.serialNumber = serialNumber;
58e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        this.subjectKeyId = subjectKeyId;
59e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
60e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
61e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public X500Name getIssuer()
62e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
63e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return issuer;
64e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
65e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
66e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public BigInteger getSerialNumber()
67e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
68e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return serialNumber;
69e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
70e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
71e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public byte[] getSubjectKeyIdentifier()
72e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
73e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return Arrays.clone(subjectKeyId);
74e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
75e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
76e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public int hashCode()
77e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
78e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        int code = Arrays.hashCode(subjectKeyId);
79e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
80e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (this.serialNumber != null)
81e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
82e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            code ^= this.serialNumber.hashCode();
83e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
84e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
85e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (this.issuer != null)
86e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
87e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            code ^= this.issuer.hashCode();
88e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
89e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
90e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return code;
91e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
92e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
93e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public boolean equals(
94e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        Object  o)
95e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
96e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (!(o instanceof X509CertificateHolderSelector))
97e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
98e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            return false;
99e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
100e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
101e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        X509CertificateHolderSelector id = (X509CertificateHolderSelector)o;
102e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
103e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return Arrays.areEqual(subjectKeyId, id.subjectKeyId)
104e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            && equalsObj(this.serialNumber, id.serialNumber)
105e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            && equalsObj(this.issuer, id.issuer);
106e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
107e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
108e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    private boolean equalsObj(Object a, Object b)
109e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
110e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return (a != null) ? a.equals(b) : b == null;
111e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
112e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
113e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public boolean match(Object obj)
114e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
115e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        if (obj instanceof X509CertificateHolder)
116e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
117e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            X509CertificateHolder certHldr = (X509CertificateHolder)obj;
118e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
119e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            if (this.getSerialNumber() != null)
120e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
121e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                IssuerAndSerialNumber iAndS = new IssuerAndSerialNumber(certHldr.toASN1Structure());
122e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
123e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                return iAndS.getName().equals(this.issuer)
124e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    && iAndS.getSerialNumber().getValue().equals(this.serialNumber);
125e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
126e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            else if (subjectKeyId != null)
127e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            {
128e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                Extension ext = certHldr.getExtension(Extension.subjectKeyIdentifier);
129e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
130e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                if (ext == null)
131e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                {
132e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                    return Arrays.areEqual(subjectKeyId, MSOutlookKeyIdCalculator.calculateKeyId(certHldr.getSubjectPublicKeyInfo()));
133e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                }
134e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
135e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                byte[] subKeyID = ASN1OctetString.getInstance(ext.getParsedValue()).getOctets();
136e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
137e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom                return Arrays.areEqual(subjectKeyId, subKeyID);
138e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            }
139e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
140e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        else if (obj instanceof byte[])
141e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        {
142e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom            return Arrays.areEqual(subjectKeyId, (byte[])obj);
143e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        }
144e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
145e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return false;
146e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
147e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom
148e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    public Object clone()
149e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    {
150e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom        return new X509CertificateHolderSelector(this.issuer, this.serialNumber, this.subjectKeyId);
151e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom    }
152e6bf3e8dfa2804891a82075cb469b736321b4827Brian Carlstrom}
153