Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / socket.io-client / lib / vendor / web-socket-js / flash-src / com / hurlant / crypto / cert / X509Certificate.as
1 /**\r
2  * X509Certificate\r
3  * \r
4  * A representation for a X509 Certificate, with\r
5  * methods to parse, verify and sign it.\r
6  * Copyright (c) 2007 Henri Torgemane\r
7  * \r
8  * See LICENSE.txt for full license information.\r
9  */\r
10 package com.hurlant.crypto.cert {\r
11         import com.hurlant.crypto.hash.IHash;\r
12         import com.hurlant.crypto.hash.MD2;\r
13         import com.hurlant.crypto.hash.MD5;\r
14         import com.hurlant.crypto.hash.SHA1;\r
15         import com.hurlant.crypto.rsa.RSAKey;\r
16         import com.hurlant.util.ArrayUtil;\r
17         import com.hurlant.util.Base64;\r
18         import com.hurlant.util.der.ByteString;\r
19         import com.hurlant.util.der.DER;\r
20         import com.hurlant.util.der.OID;\r
21         import com.hurlant.util.der.ObjectIdentifier;\r
22         import com.hurlant.util.der.PEM;\r
23         import com.hurlant.util.der.PrintableString;\r
24         import com.hurlant.util.der.Sequence;\r
25         import com.hurlant.util.der.Type;\r
26         \r
27         import flash.utils.ByteArray;\r
28         \r
29         public class X509Certificate {\r
30                 private var _loaded:Boolean;\r
31                 private var _param:*;\r
32                 private var _obj:Object;\r
33                 public function X509Certificate(p:*) {\r
34                         _loaded = false;\r
35                         _param = p;\r
36                         // lazy initialization, to avoid unnecessary parsing of every builtin CA at start-up.\r
37                 }\r
38                 private function load():void {\r
39                         if (_loaded) return;\r
40                         var p:* = _param;\r
41                         var b:ByteArray;\r
42                         if (p is String) {\r
43                                 b = PEM.readCertIntoArray(p as String);\r
44                         } else if (p is ByteArray) {\r
45                                 b = p;\r
46                         }\r
47                         if (b!=null) {\r
48                                 _obj = DER.parse(b, Type.TLS_CERT);\r
49                                 _loaded = true;\r
50                         } else {\r
51                                 throw new Error("Invalid x509 Certificate parameter: "+p);\r
52                         }\r
53                 }\r
54                 public function isSigned(store:X509CertificateCollection, CAs:X509CertificateCollection, time:Date=null):Boolean {\r
55                         load();\r
56                         // check timestamps first. cheapest.\r
57                         if (time==null) {\r
58                                 time = new Date;\r
59                         }\r
60                         var notBefore:Date = getNotBefore();\r
61                         var notAfter:Date = getNotAfter();\r
62                         if (time.getTime()<notBefore.getTime()) return false; // cert isn't born yet.\r
63                         if (time.getTime()>notAfter.getTime()) return false;  // cert died of old age.\r
64                         // check signature.\r
65                         var subject:String = getIssuerPrincipal();\r
66                         // try from CA first, since they're treated better.\r
67                         var parent:X509Certificate = CAs.getCertificate(subject);\r
68                         var parentIsAuthoritative:Boolean = false;\r
69                         if (parent == null) {\r
70                                 parent = store.getCertificate(subject);\r
71                                 if (parent == null) {\r
72                                         return false; // issuer not found\r
73                                 }\r
74                         } else {\r
75                                 parentIsAuthoritative = true;\r
76                         }\r
77                         if (parent == this) { // pathological case. avoid infinite loop\r
78                                 return false; // isSigned() returns false if we're self-signed.\r
79                         }\r
80                         if (!(parentIsAuthoritative&&parent.isSelfSigned(time)) &&\r
81                                 !parent.isSigned(store, CAs, time)) {\r
82                                 return false;\r
83                         }\r
84                         var key:RSAKey = parent.getPublicKey();\r
85                         return verifyCertificate(key);\r
86                 }\r
87                 public function isSelfSigned(time:Date):Boolean {\r
88                         load();\r
89                         \r
90                         var key:RSAKey = getPublicKey();\r
91                         return verifyCertificate(key);\r
92                 }\r
93                 private function verifyCertificate(key:RSAKey):Boolean {\r
94                         var algo:String = getAlgorithmIdentifier();\r
95                         var hash:IHash;\r
96                         var oid:String;\r
97                         switch (algo) {\r
98                                 case OID.SHA1_WITH_RSA_ENCRYPTION:\r
99                                         hash = new SHA1;\r
100                                         oid = OID.SHA1_ALGORITHM;\r
101                                         break;\r
102                                 case OID.MD2_WITH_RSA_ENCRYPTION:\r
103                                         hash = new MD2;\r
104                                         oid = OID.MD2_ALGORITHM;\r
105                                         break;\r
106                                 case OID.MD5_WITH_RSA_ENCRYPTION:\r
107                                         hash = new MD5;\r
108                                         oid = OID.MD5_ALGORITHM;\r
109                                         break;\r
110                                 default:\r
111                                         return false;\r
112                         }\r
113                         var data:ByteArray = _obj.signedCertificate_bin;\r
114                         var buf:ByteArray = new ByteArray;\r
115                         key.verify(_obj.encrypted, buf, _obj.encrypted.length);\r
116                         buf.position=0;\r
117                         data = hash.hash(data);\r
118                         var obj:Object = DER.parse(buf, Type.RSA_SIGNATURE);\r
119                         if (obj.algorithm.algorithmId.toString() != oid) {\r
120                                 return false; // wrong algorithm\r
121                         }\r
122                         if (!ArrayUtil.equals(obj.hash, data)) {\r
123                                 return false; // hashes don't match\r
124                         }\r
125                         return true;\r
126                 }\r
127                 \r
128                 /**\r
129                  * This isn't used anywhere so far.\r
130                  * It would become useful if we started to offer facilities\r
131                  * to generate and sign X509 certificates.\r
132                  * \r
133                  * @param key\r
134                  * @param algo\r
135                  * @return \r
136                  * \r
137                  */\r
138                 private function signCertificate(key:RSAKey, algo:String):ByteArray {\r
139                         var hash:IHash;\r
140                         var oid:String;\r
141                         switch (algo) {\r
142                                 case OID.SHA1_WITH_RSA_ENCRYPTION:\r
143                                         hash = new SHA1;\r
144                                         oid = OID.SHA1_ALGORITHM;\r
145                                         break;\r
146                                 case OID.MD2_WITH_RSA_ENCRYPTION:\r
147                                         hash = new MD2;\r
148                                         oid = OID.MD2_ALGORITHM;\r
149                                         break;\r
150                                 case OID.MD5_WITH_RSA_ENCRYPTION:\r
151                                         hash = new MD5;\r
152                                         oid = OID.MD5_ALGORITHM;\r
153                                         break;\r
154                                 default:\r
155                                         return null\r
156                         }\r
157                         var data:ByteArray = _obj.signedCertificate_bin;\r
158                         data = hash.hash(data);\r
159                         var seq1:Sequence = new Sequence;\r
160                         seq1[0] = new Sequence;\r
161                         seq1[0][0] = new ObjectIdentifier(0,0, oid);\r
162                         seq1[0][1] = null;\r
163                         seq1[1] = new ByteString;\r
164                         seq1[1].writeBytes(data);\r
165                         data = seq1.toDER();\r
166                         var buf:ByteArray = new ByteArray;\r
167                         key.sign(data, buf, data.length);\r
168                         return buf;\r
169                 }\r
170                 \r
171                 public function getPublicKey():RSAKey {\r
172                         load();\r
173                         var pk:ByteArray = _obj.signedCertificate.subjectPublicKeyInfo.subjectPublicKey as ByteArray;\r
174                         pk.position = 0;\r
175                         var rsaKey:Object = DER.parse(pk, [{name:"N"},{name:"E"}]);\r
176                         return new RSAKey(rsaKey.N, rsaKey.E.valueOf());\r
177                 }\r
178                 \r
179                 /**\r
180                  * Returns a subject principal, as an opaque base64 string.\r
181                  * This is only used as a hash key for known certificates.\r
182                  * \r
183                  * Note that this assumes X509 DER-encoded certificates are uniquely encoded,\r
184                  * as we look for exact matches between Issuer and Subject fields.\r
185                  * \r
186                  */\r
187                 public function getSubjectPrincipal():String {\r
188                         load();\r
189                         return Base64.encodeByteArray(_obj.signedCertificate.subject_bin);\r
190                 }\r
191                 /**\r
192                  * Returns an issuer principal, as an opaque base64 string.\r
193                  * This is only used to quickly find matching parent certificates.\r
194                  * \r
195                  * Note that this assumes X509 DER-encoded certificates are uniquely encoded,\r
196                  * as we look for exact matches between Issuer and Subject fields.\r
197                  * \r
198                  */\r
199                 public function getIssuerPrincipal():String {\r
200                         load();\r
201                         return Base64.encodeByteArray(_obj.signedCertificate.issuer_bin);\r
202                 }\r
203                 public function getAlgorithmIdentifier():String {\r
204                         return _obj.algorithmIdentifier.algorithmId.toString();\r
205                 }\r
206                 public function getNotBefore():Date {\r
207                         return _obj.signedCertificate.validity.notBefore.date;\r
208                 }\r
209                 public function getNotAfter():Date {\r
210                         return _obj.signedCertificate.validity.notAfter.date;\r
211                 }\r
212                 \r
213                 public function getCommonName():String {\r
214                         var subject:Sequence = _obj.signedCertificate.subject;\r
215                         return (subject.findAttributeValue(OID.COMMON_NAME) as PrintableString).getString();\r
216                 }\r
217         }\r
218 }