1 /** 2 * --------- 3 * |.##> <##.| Open Smart Card Development Platform (www.openscdp.org) 4 * |# #| 5 * |# #| Copyright (c) 1999-2018 CardContact Software & System Consulting 6 * |'##> <##'| Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de) 7 * --------- 8 * 9 * This file is part of OpenSCDP. 10 * 11 * OpenSCDP is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License version 2 as 13 * published by the Free Software Foundation. 14 * 15 * OpenSCDP is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with OpenSCDP; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 23 * 24 * @fileoverview X509Name - Class to support X500 Names 25 */ 26 27 // Name ::= CHOICE { 28 // RDNSequence } 29 // 30 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 31 // 32 // RelativeDistinguishedName ::= 33 // SET OF AttributeTypeAndValue 34 // 35 // AttributeTypeAndValue ::= SEQUENCE { 36 // type AttributeType, 37 // value AttributeValue } 38 // 39 // AttributeType ::= OBJECT IDENTIFIER 40 // 41 // AttributeValue ::= ANY DEFINED BY AttributeType 42 43 44 45 X509Name.name = "550429"; 46 X509Name.surname = "550404"; 47 X509Name.givenname = "55042A"; 48 X509Name.initials = "55042B"; 49 X509Name.generationQualifier = "55042C"; 50 X509Name.commonName = "550403"; 51 X509Name.localityName = "550407"; 52 X509Name.stateOrProvinceName = "550408"; 53 X509Name.organizationName = "55040A"; 54 X509Name.organizationalUnitName = "55040B"; 55 X509Name.title = "55040C"; 56 X509Name.dnQualifier = "55042E"; 57 X509Name.countryName = "550406"; 58 X509Name.serialNumber = "550405"; 59 X509Name.emailAddress = "2A864886F70D010901"; 60 61 62 63 function X509Name(subjectDN) { 64 this.rdn = new Array(); 65 this.parseRDNSequence(subjectDN); 66 } 67 68 exports.X509Name = X509Name; 69 70 71 72 X509Name.prototype.parseRDNSequence = function(rdnSeq) { 73 if (rdnSeq instanceof ASN1) { 74 if (!rdnSeq.isconstructed) { 75 throw new GPError("X509Name", GPError.INVALID_DATA, 1, "Name must be constructed"); 76 } 77 78 if (rdnSeq.tag != ASN1.SEQUENCE) { 79 throw new GPError("X509Name", GPError.INVALID_DATA, 1, "RDNSequence must be SEQUENCE"); 80 } 81 82 for (var i = 0; i < rdnSeq.elements; i++) { 83 var set = rdnSeq.get(i) 84 if (set.tag != ASN1.SET) { 85 throw new GPError("X509Name", GPError.INVALID_DATA, 1, "RDNSequence must only contain SETs"); 86 } 87 for (var j = 0; j < set.elements; j++) { 88 var attr = set.get(j); 89 if (attr.tag != ASN1.SEQUENCE) { 90 throw new GPError("X509Name", GPError.INVALID_DATA, 1, "AttributeTypeAndValue must be SEQUENCE"); 91 } 92 if (attr.elements != 2) { 93 throw new GPError("X509Name", GPError.INVALID_DATA, 1, "AttributeTypeAndValue must have 2 elements"); 94 } 95 var attrType = attr.get(0); 96 if (attrType.tag != ASN1.OBJECT_IDENTIFIER) { 97 throw new GPError("X509Name", GPError.INVALID_DATA, 1, "AttributeType must be OBJECT IDENTIFIER"); 98 } 99 var oid = attrType.value.toString(HEX); 100 var attrValue = attr.get(1); 101 this.rdn[oid] = attrValue; 102 } 103 } 104 } else { 105 throw new GPError("X509Name", GPError.INVALID_TYPE, 1, "Argument must be of type ASN1"); 106 } 107 } 108 109 110 111 X509Name.prototype.hasRDN = function(oid) { 112 return this.rdn[oid] != undefined; 113 } 114 115 116 117 X509Name.prototype.getRDNAsString = function(oid) { 118 var r = this.rdn[oid]; 119 if (r == undefined) { 120 throw new GPError("X509Name", GPError.INVALID_INDEX,0,"No matching RDN found"); 121 } 122 123 if (r.tag == ASN1.UTF8String) { 124 return r.value.toString(UTF8); 125 } else { 126 return r.value.toString(ASCII); 127 } 128 } 129 130 131 132 X509Name.prototype.toString = function() { 133 var result = ""; 134 135 if (this.hasRDN(X509Name.countryName)) { 136 result += "C=" + this.getRDNAsString(X509Name.countryName); 137 } 138 139 if (this.hasRDN(X509Name.stateOrProvinceName)) { 140 if (result.length > 0) 141 result += ","; 142 result += "ST=" + this.getRDNAsString(X509Name.stateOrProvinceName); 143 } 144 145 if (this.hasRDN(X509Name.organizationName)) { 146 if (result.length > 0) 147 result += ","; 148 149 result += "O=" + this.getRDNAsString(X509Name.organizationName); 150 } 151 152 if (this.hasRDN(X509Name.organizationalUnitName)) { 153 if (result.length > 0) 154 result += ","; 155 156 result += "OU=" + this.getRDNAsString(X509Name.organizationalUnitName); 157 } 158 159 if (this.hasRDN(X509Name.localityName)) { 160 if (result.length > 0) 161 result += ","; 162 result += "L=" + this.getRDNAsString(X509Name.localityName); 163 } 164 165 if (this.hasRDN(X509Name.title)) { 166 if (result.length > 0) 167 result += ","; 168 result += "T=" + this.getRDNAsString(X509Name.title); 169 } 170 171 if (this.hasRDN(X509Name.givenname)) { 172 if (result.length > 0) 173 result += ","; 174 result += "G=" + this.getRDNAsString(X509Name.givenname); 175 } 176 177 if (this.hasRDN(X509Name.surname)) { 178 if (result.length > 0) 179 result += ","; 180 result += "S=" + this.getRDNAsString(X509Name.surname); 181 } 182 183 if (this.hasRDN(X509Name.generationQualifier)) { 184 if (result.length > 0) 185 result += ","; 186 result += "generationQualifier=" + this.getRDNAsString(X509Name.generationQualifier); 187 } 188 189 if (this.hasRDN(X509Name.name)) { 190 if (result.length > 0) 191 result += ","; 192 result += "N=" + this.getRDNAsString(X509Name.name); 193 } 194 195 if (this.hasRDN(X509Name.initials)) { 196 if (result.length > 0) 197 result += ","; 198 result += "initials=" + this.getRDNAsString(X509Name.initials); 199 } 200 201 if (this.hasRDN(X509Name.commonName)) { 202 if (result.length > 0) 203 result += ","; 204 result += "CN=" + this.getRDNAsString(X509Name.commonName); 205 } 206 207 208 if (this.hasRDN(X509Name.serialNumber)) { 209 if (result.length > 0) 210 result += ","; 211 result += "SERIALNUMBER=" + this.getRDNAsString(X509Name.serialNumber); 212 } 213 214 if (this.hasRDN(X509Name.dnQualifier)) { 215 if (result.length > 0) 216 result += ","; 217 result += "DNQ=" + this.getRDNAsString(X509Name.dnQualifier); 218 } 219 220 if (this.hasRDN(X509Name.emailAddress)) { 221 if (result.length > 0) 222 result += ","; 223 result += "E=" + this.getRDNAsString(X509Name.emailAddress); 224 } 225 226 return result; 227 } 228