/** * Create a new user ID token with the specified user. * * @param ctx MSL context. * @param renewalWindow the renewal window. * @param expiration the expiration. * @param masterToken the master token. * @param serialNumber the user ID token serial number. * @param issuerData the issuer data. May be null. * @param user the MSL user. * @throws MslEncodingException if there is an error encoding the JSON data. * @throws MslCryptoException if there is an error encrypting or signing the token data. */ public UserIdToken( final MslContext ctx, final Date renewalWindow, final Date expiration, final MasterToken masterToken, final long serialNumber, final JSONObject issuerData, final MslUser user) throws MslEncodingException, MslCryptoException { // The expiration must appear after the renewal window. if (expiration.before(renewalWindow)) throw new MslInternalException( "Cannot construct a user ID token that expires before its renewal window opens."); // A master token must be provided. if (masterToken == null) throw new MslInternalException("Cannot construct a user ID token without a master token."); // The serial number must be within range. if (serialNumber < 0 || serialNumber > MslConstants.MAX_LONG_VALUE) throw new MslInternalException( "Serial number " + serialNumber + " is outside the valid range."); this.ctx = ctx; this.renewalWindow = renewalWindow.getTime() / MILLISECONDS_PER_SECOND; this.expiration = expiration.getTime() / MILLISECONDS_PER_SECOND; this.mtSerialNumber = masterToken.getSerialNumber(); this.serialNumber = serialNumber; this.issuerData = issuerData; this.user = user; // Construct the user data. final JSONObject userData = new JSONObject(); try { if (this.issuerData != null) userData.put(KEY_ISSUER_DATA, this.issuerData); userData.put(KEY_IDENTITY, user.getEncoded()); this.userdata = userData.toString().getBytes(MslConstants.DEFAULT_CHARSET); } catch (final JSONException e) { throw new MslEncodingException(MslError.JSON_ENCODE_ERROR, "userdata", e); } try { // Encrypt the user data. final ICryptoContext cryptoContext = ctx.getMslCryptoContext(); final byte[] ciphertext = cryptoContext.encrypt(this.userdata); // Construct the token data. try { final JSONObject tokenDataJO = new JSONObject(); tokenDataJO.put(KEY_RENEWAL_WINDOW, this.renewalWindow); tokenDataJO.put(KEY_EXPIRATION, this.expiration); tokenDataJO.put(KEY_MASTER_TOKEN_SERIAL_NUMBER, this.mtSerialNumber); tokenDataJO.put(KEY_SERIAL_NUMBER, this.serialNumber); tokenDataJO.put(KEY_USERDATA, Base64.encode(ciphertext)); this.tokendata = tokenDataJO.toString().getBytes(MslConstants.DEFAULT_CHARSET); } catch (final JSONException e) { throw new MslEncodingException(MslError.JSON_ENCODE_ERROR, "usertokendata", e) .setMasterToken(masterToken); } // Sign the token data. this.signature = cryptoContext.sign(this.tokendata); this.verified = true; } catch (final MslCryptoException e) { e.setMasterToken(masterToken); throw e; } }