PageRenderTime 63ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/js/lib/Socket.IO-node/support/socket.io-client/lib/vendor/web-socket-js/flash-src/com/hurlant/crypto/cert/X509Certificate.as

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