View Javadoc
1   /*
2    * Copyright 2014 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.handler.ssl.util;
17  
18  import io.netty.util.internal.ObjectUtil;
19  
20  import java.io.ByteArrayInputStream;
21  import java.math.BigInteger;
22  import java.security.InvalidKeyException;
23  import java.security.NoSuchAlgorithmException;
24  import java.security.NoSuchProviderException;
25  import java.security.Principal;
26  import java.security.Provider;
27  import java.security.PublicKey;
28  import java.security.SignatureException;
29  import java.security.cert.CertificateEncodingException;
30  import java.security.cert.CertificateException;
31  import java.security.cert.CertificateExpiredException;
32  import java.security.cert.CertificateFactory;
33  import java.security.cert.CertificateNotYetValidException;
34  import java.security.cert.CertificateParsingException;
35  import java.security.cert.X509Certificate;
36  import java.util.Collection;
37  import java.util.Date;
38  import java.util.List;
39  import java.util.Set;
40  import javax.security.auth.x500.X500Principal;
41  
42  public final class LazyX509Certificate extends X509Certificate {
43  
44      static final CertificateFactory X509_CERT_FACTORY;
45      static {
46          try {
47              X509_CERT_FACTORY = CertificateFactory.getInstance("X.509");
48          } catch (CertificateException e) {
49              throw new ExceptionInInitializerError(e);
50          }
51      }
52  
53      private final byte[] bytes;
54      private X509Certificate wrapped;
55  
56      /**
57       * Creates a new instance which will lazy parse the given bytes. Be aware that the bytes will not be cloned.
58       */
59      public LazyX509Certificate(byte[] bytes) {
60          this.bytes = ObjectUtil.checkNotNull(bytes, "bytes");
61      }
62  
63      @Override
64      public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException {
65          unwrap().checkValidity();
66      }
67  
68      @Override
69      public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException {
70          unwrap().checkValidity(date);
71      }
72  
73      @Override
74      public X500Principal getIssuerX500Principal() {
75          return unwrap().getIssuerX500Principal();
76      }
77  
78      @Override
79      public X500Principal getSubjectX500Principal() {
80          return unwrap().getSubjectX500Principal();
81      }
82  
83      @Override
84      public List<String> getExtendedKeyUsage() throws CertificateParsingException {
85          return unwrap().getExtendedKeyUsage();
86      }
87  
88      @Override
89      public Collection<List<?>> getSubjectAlternativeNames() throws CertificateParsingException {
90          return unwrap().getSubjectAlternativeNames();
91      }
92  
93      @Override
94      public Collection<List<?>> getIssuerAlternativeNames() throws CertificateParsingException {
95          return unwrap().getIssuerAlternativeNames();
96      }
97  
98      @Override
99      public void verify(PublicKey key, Provider sigProvider)
100             throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
101         unwrap().verify(key, sigProvider);
102     }
103 
104     @Override
105     public int getVersion() {
106         return unwrap().getVersion();
107     }
108 
109     @Override
110     public BigInteger getSerialNumber() {
111         return unwrap().getSerialNumber();
112     }
113 
114     @Override
115     public Principal getIssuerDN() {
116         return unwrap().getIssuerDN();
117     }
118 
119     @Override
120     public Principal getSubjectDN() {
121         return unwrap().getSubjectDN();
122     }
123 
124     @Override
125     public Date getNotBefore() {
126         return unwrap().getNotBefore();
127     }
128 
129     @Override
130     public Date getNotAfter() {
131         return unwrap().getNotAfter();
132     }
133 
134     @Override
135     public byte[] getTBSCertificate() throws CertificateEncodingException {
136         return unwrap().getTBSCertificate();
137     }
138 
139     @Override
140     public byte[] getSignature() {
141         return unwrap().getSignature();
142     }
143 
144     @Override
145     public String getSigAlgName() {
146         return unwrap().getSigAlgName();
147     }
148 
149     @Override
150     public String getSigAlgOID() {
151         return unwrap().getSigAlgOID();
152     }
153 
154     @Override
155     public byte[] getSigAlgParams() {
156         return unwrap().getSigAlgParams();
157     }
158 
159     @Override
160     public boolean[] getIssuerUniqueID() {
161         return unwrap().getIssuerUniqueID();
162     }
163 
164     @Override
165     public boolean[] getSubjectUniqueID() {
166         return unwrap().getSubjectUniqueID();
167     }
168 
169     @Override
170     public boolean[] getKeyUsage() {
171         return unwrap().getKeyUsage();
172     }
173 
174     @Override
175     public int getBasicConstraints() {
176         return unwrap().getBasicConstraints();
177     }
178 
179     @Override
180     public byte[] getEncoded() {
181         return bytes.clone();
182     }
183 
184     @Override
185     public void verify(PublicKey key)
186             throws CertificateException, NoSuchAlgorithmException,
187             InvalidKeyException, NoSuchProviderException, SignatureException {
188         unwrap().verify(key);
189     }
190 
191     @Override
192     public void verify(PublicKey key, String sigProvider)
193             throws CertificateException, NoSuchAlgorithmException, InvalidKeyException,
194             NoSuchProviderException, SignatureException {
195         unwrap().verify(key, sigProvider);
196     }
197 
198     @Override
199     public String toString() {
200         return unwrap().toString();
201     }
202 
203     @Override
204     public PublicKey getPublicKey() {
205         return unwrap().getPublicKey();
206     }
207 
208     @Override
209     public boolean hasUnsupportedCriticalExtension() {
210         return unwrap().hasUnsupportedCriticalExtension();
211     }
212 
213     @Override
214     public Set<String> getCriticalExtensionOIDs() {
215         return unwrap().getCriticalExtensionOIDs();
216     }
217 
218     @Override
219     public Set<String> getNonCriticalExtensionOIDs() {
220         return unwrap().getNonCriticalExtensionOIDs();
221     }
222 
223     @Override
224     public byte[] getExtensionValue(String oid) {
225         return unwrap().getExtensionValue(oid);
226     }
227 
228     private X509Certificate unwrap() {
229         X509Certificate wrapped = this.wrapped;
230         if (wrapped == null) {
231             try {
232                 wrapped = this.wrapped = (X509Certificate) X509_CERT_FACTORY.generateCertificate(
233                         new ByteArrayInputStream(bytes));
234             } catch (CertificateException e) {
235                 throw new IllegalStateException(e);
236             }
237         }
238         return wrapped;
239     }
240 }