1 /*! jwsjs-2.0.2 (c) 2010-2015 Kenji Urushima | kjur.github.com/jsrsasign/license
  2  */
  3 /*
  4  * jwsjs.js - JSON Web Signature JSON Serialization (JWSJS) Class
  5  *
  6  * version: 2.0.2 (2015 May 29)
  7  *
  8  * Copyright (c) 2010-2015 Kenji Urushima (kenji.urushima@gmail.com)
  9  *
 10  * This software is licensed under the terms of the MIT License.
 11  * http://kjur.github.com/jsrsasign/license/
 12  *
 13  * The above copyright and license notice shall be 
 14  * included in all copies or substantial portions of the Software.
 15  */
 16 
 17 /**
 18  * @fileOverview
 19  * @name jwsjs-2.0.js
 20  * @author Kenji Urushima kenji.urushima@gmail.com
 21  * @version 2.0.2 (2015 May 29)
 22  * @since jsjws 1.2, jsrsasign 4.8.0
 23  * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
 24  */
 25 
 26 if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
 27 if (typeof KJUR.jws == "undefined" || !KJUR.jws) KJUR.jws = {};
 28 
 29 /**
 30  * JSON Web Signature JSON Serialization (JWSJS) class.<br/>
 31  * @class JSON Web Signature JSON Serialization (JWSJS) class
 32  * @name KJUR.jws.JWSJS
 33  * @property {array of String} aHeader array of Encoded JWS Headers
 34  * @property {String} sPayload Encoded JWS payload
 35  * @property {array of String} aSignature array of Encoded JWS signature value
 36  * @author Kenji Urushima
 37  * @version 1.0 (18 May 2012)
 38  * @requires base64x.js, json-sans-eval.js, jws.js and jsrsasign library
 39  * @see <a href="http://kjur.github.com/jsjws/">'jwjws'(JWS JavaScript Library) home page http://kjur.github.com/jsjws/</a>
 40  * @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a>
 41  * @see <a href="http://tools.ietf.org/html/draft-jones-json-web-signature-json-serialization-01">IETF I-D JSON Web Signature JSON Serialization (JWS-JS) specification</a>
 42  */
 43 KJUR.jws.JWSJS = function() {
 44 	var ns1 = KJUR.jws.JWS;
 45 
 46     this.aHeader = [];
 47     this.sPayload = "";
 48     this.aSignature = [];
 49 
 50     // == initialize ===================================================================
 51     /**
 52      * (re-)initialize this object.<br/>
 53      * @name init
 54      * @memberOf KJUR.jws.JWSJS
 55      * @function
 56      */
 57     this.init = function() {
 58 		this.aHeader = [];
 59 		this.sPayload = "";
 60 		this.aSignature = [];
 61     };
 62 
 63     /**
 64      * (re-)initialize and set first signature with JWS.<br/>
 65      * @name initWithJWS
 66      * @memberOf KJUR.jws.JWSJS
 67      * @param {String} sJWS JWS signature to set
 68      * @function
 69      */
 70     this.initWithJWS = function(sJWS) {
 71 		this.init();
 72 
 73 		var jws = new KJUR.jws.JWS();
 74 		jws.parseJWS(sJWS);
 75 
 76 		this.aHeader.push(jws.parsedJWS.headB64U);
 77 		this.sPayload = jws.parsedJWS.payloadB64U;
 78 		this.aSignature.push(jws.parsedJWS.sigvalB64U);
 79     };
 80 
 81     // == add signature ===================================================================
 82     /**
 83      * add a signature to existing JWS-JS by Header and PKCS1 private key.<br/>
 84      * @name addSignatureByHeaderKey
 85      * @memberOf KJUR.jws.JWSJS
 86      * @function
 87      * @param {String} sHead JSON string of JWS Header for adding signature.
 88      * @param {String} sPemPrvKey string of PKCS1 private key
 89      */
 90     this.addSignatureByHeaderKey = function(sHead, sPemPrvKey) {
 91 		var sPayload = b64utoutf8(this.sPayload);
 92 
 93 		var jws = new KJUR.jws.JWS();
 94 		var sJWS = jws.generateJWSByP1PrvKey(sHead, sPayload, sPemPrvKey);
 95   
 96 		this.aHeader.push(jws.parsedJWS.headB64U);
 97 		this.aSignature.push(jws.parsedJWS.sigvalB64U);
 98     };
 99 
100     /**
101      * add a signature to existing JWS-JS by Header, Payload and PKCS1 private key.<br/>
102      * This is to add first signature to JWS-JS object.
103      * @name addSignatureByHeaderPayloadKey
104      * @memberOf KJUR.jws.JWSJS
105      * @function
106      * @param {String} sHead JSON string of JWS Header for adding signature.
107      * @param {String} sPayload string of JWS Payload for adding signature.
108      * @param {String} sPemPrvKey string of PKCS1 private key
109      */
110     this.addSignatureByHeaderPayloadKey = function(sHead, sPayload, sPemPrvKey) {
111 		var jws = new KJUR.jws.JWS();
112 		var sJWS = jws.generateJWSByP1PrvKey(sHead, sPayload, sPemPrvKey);
113   
114 		this.aHeader.push(jws.parsedJWS.headB64U);
115 		this.sPayload = jws.parsedJWS.payloadB64U;
116 		this.aSignature.push(jws.parsedJWS.sigvalB64U);
117     };
118 
119     // == verify signature ===================================================================
120     /**
121      * verify JWS-JS object with array of certificate string.<br/>
122      * @name verifyWithCerts
123      * @memberOf KJUR.jws.JWSJS
124      * @function
125      * @param {array of String} aCert array of string for X.509 PEM certificate.
126      * @return 1 if signature is valid.
127      * @throw if JWS-JS signature is invalid.
128      */
129     this.verifyWithCerts = function(aCert) {
130 		if (this.aHeader.length != aCert.length) 
131 			throw "num headers does not match with num certs";
132 		if (this.aSignature.length != aCert.length) 
133 			throw "num signatures does not match with num certs";
134 
135 		var payload = this.sPayload;
136 		var errMsg = "";
137 		for (var i = 0; i < aCert.length; i++) {
138 			var cert = aCert[i];
139 			var header = this.aHeader[i];
140 			var sig = this.aSignature[i];
141 			var sJWS = header + "." + payload + "." + sig;
142 
143 			var jws = new KJUR.jws.JWS();
144 			try {
145 				var result = jws.verifyJWSByPemX509Cert(sJWS, cert);
146 				if (result != 1) {
147 					errMsg += (i + 1) + "th signature unmatch. ";
148 				}
149 			} catch (ex) {
150 				errMsg += (i + 1) + "th signature fail(" + ex + "). ";
151 			}
152 		}
153 
154 		if (errMsg == "") {
155 			return 1;
156 		} else {
157 			throw errMsg;
158 		}
159     };
160 
161     /**
162      * read JWS-JS string.<br/>
163      * @name raedJWSJS
164      * @memberOf KJUR.jws.JWSJS
165      * @function
166      * @param {String} string of JWS-JS to load.
167      * @throw if sJWSJS is malformed or not JSON string.
168      */
169     this.readJWSJS = function(sJWSJS) {
170 		var oJWSJS = ns1.readSafeJSONString(sJWSJS);
171 		if (oJWSJS == null) throw "argument is not JSON string: " + sJWSJS;
172 
173 		this.aHeader = oJWSJS.headers;
174 		this.sPayload = oJWSJS.payload;
175 		this.aSignature = oJWSJS.signatures;
176     };
177 
178     // == utility ===================================================================
179     /**
180      * get JSON object for this JWS-JS object.<br/>
181      * @name getJSON
182      * @memberOf KJUR.jws.JWSJS
183      * @function
184      */
185     this.getJSON = function() {
186 		return { "headers": this.aHeader,
187 				 "payload": this.sPayload,
188 				 "signatures": this.aSignature }; 
189     };
190 
191     /**
192      * check if this JWS-JS object is empty.<br/>
193      * @name isEmpty
194      * @memberOf KJUR.jws.JWSJS
195      * @function
196      * @return 1 if there is no signatures in this object, otherwise 0.
197      */
198     this.isEmpty = function() {
199 		if (this.aHeader.length == 0) return 1; 
200 		return 0;
201     };
202 };
203 
204