/* (non-Javadoc) * @see org.json.JSONString#toJSONString() */ @Override public final String toJSONString() { try { final JSONObject jsonObj = new JSONObject(); jsonObj.put(KEY_TOKENDATA, Base64.encode(tokendata)); jsonObj.put(KEY_SIGNATURE, Base64.encode(signature)); return jsonObj.toString(); } catch (final JSONException e) { throw new MslInternalException("Error encoding " + this.getClass().getName() + " JSON.", e); } }
/* (non-Javadoc) * @see com.netflix.msl.entityauth.EntityAuthenticationData#getAuthData() */ @Override public JSONObject getAuthData() throws MslEncodingException { final JSONObject jsonObj = new JSONObject(); try { jsonObj.put(KEY_X509_CERT, Base64.encode(x509cert.getEncoded())); } catch (final JSONException e) { throw new MslEncodingException(MslError.JSON_ENCODE_ERROR, "X.509 authdata", e); } catch (final CertificateEncodingException e) { throw new MslEncodingException(MslError.X509CERT_ENCODE_ERROR, "X.509 authdata", e); } return jsonObj; }
/* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { try { final JSONObject tokendataJO = new JSONObject(); tokendataJO.put(KEY_RENEWAL_WINDOW, renewalWindow); tokendataJO.put(KEY_EXPIRATION, expiration); tokendataJO.put(KEY_MASTER_TOKEN_SERIAL_NUMBER, mtSerialNumber); tokendataJO.put(KEY_SERIAL_NUMBER, serialNumber); tokendataJO.put(KEY_USERDATA, "(redacted)"); final JSONObject jsonObj = new JSONObject(); jsonObj.put(KEY_TOKENDATA, tokendataJO); jsonObj.put(KEY_SIGNATURE, Base64.encode(signature)); return jsonObj.toString(); } catch (final JSONException e) { throw new MslInternalException("Error encoding " + this.getClass().getName() + " JSON.", e); } }
/** * Construct a new X.509 asymmetric keys authentication data instance from the provided JSON * object. * * @param x509AuthJO the authentication data JSON object. * @throws MslCryptoException if the X.509 certificate data cannot be parsed. * @throws MslEncodingException if the X.509 certificate cannot be found. */ X509AuthenticationData(final JSONObject x509AuthJO) throws MslCryptoException, MslEncodingException { super(EntityAuthenticationScheme.X509); // Extract X.509 certificate representation. final String x509; try { x509 = x509AuthJO.getString(KEY_X509_CERT); } catch (final JSONException e) { throw new MslEncodingException( MslError.JSON_PARSE_ERROR, "X.509 authdata " + x509AuthJO.toString(), e); } // Get the X.509 certificate factory. final CertificateFactory factory; try { factory = CertificateFactory.getInstance("X.509"); } catch (final CertificateException e) { throw new MslInternalException("No certificate X.509 certificate factory.", e); } // Create X.509 cert. final byte[] x509bytes; try { x509bytes = Base64.decode(x509); } catch (final IllegalArgumentException e) { throw new MslCryptoException(MslError.X509CERT_INVALID, x509, e); } try { final ByteArrayInputStream bais = new ByteArrayInputStream(x509bytes); x509cert = (X509Certificate) factory.generateCertificate(bais); identity = x509cert.getSubjectX500Principal().getName(); } catch (final CertificateException e) { throw new MslCryptoException(MslError.X509CERT_PARSE_ERROR, x509, e); } }
/** * @param localIdentity local entity identity. * @param remoteIdentity remote entity identity. * @param remoteRsaPubkeyB64 base64-encoded remote entity public key in X.509 format. * @param email user email address. May be {@code null}. * @param password user password. May be {@code null}. * @throws NoSuchAlgorithmException if the RSA algorithm is not supported. * @throws InvalidKeySpecException if the public key is invalid. */ public Oneshot( final String localIdentity, final String remoteIdentity, final String remoteRsaPubkeyB64, final String email, final String password) throws NoSuchAlgorithmException, InvalidKeySpecException { // Create MSL control. this.ctrl = new MslControl(0); // Setup remote entity public key. final byte[] pubkeyBytes = Base64.decode(remoteRsaPubkeyB64); final X509EncodedKeySpec pubkeySpec = new X509EncodedKeySpec(pubkeyBytes); final KeyFactory factory = KeyFactory.getInstance("RSA"); final PublicKey pubkey = factory.generatePublic(pubkeySpec); final OneshotRsaStore rsaStore = new OneshotRsaStore(remoteIdentity, pubkey); // Create MSL context. this.ctx = new OneshotMslContext(localIdentity, rsaStore); // Save user account information. this.email = email; this.password = password; }
/** * Create a new user ID token from the provided JSON object. The associated master token must be * provided to verify the user ID token. * * @param ctx MSL context. * @param userIdTokenJO user ID token JSON object. * @param masterToken the master token. * @throws MslEncodingException if there is an error parsing the JSON, the token data is missing * or invalid, or the signature is invalid. * @throws MslCryptoException if there is an error verifying the token data. * @throws MslException if the user ID token master token serial number does not match the master * token serial number, or the expiration timestamp occurs before the renewal window, or the * user data is missing or invalid, or the user ID token master token serial number is out of * range, or the user ID token serial number is out of range. */ public UserIdToken( final MslContext ctx, final JSONObject userIdTokenJO, final MasterToken masterToken) throws MslEncodingException, MslCryptoException, MslException { this.ctx = ctx; // Grab the crypto context. final ICryptoContext cryptoContext = ctx.getMslCryptoContext(); // Verify the JSON representation. try { try { tokendata = Base64.decode(userIdTokenJO.getString(KEY_TOKENDATA)); } catch (final IllegalArgumentException e) { throw new MslEncodingException( MslError.USERIDTOKEN_TOKENDATA_INVALID, "useridtoken " + userIdTokenJO.toString(), e) .setMasterToken(masterToken); } if (tokendata == null || tokendata.length == 0) throw new MslEncodingException( MslError.USERIDTOKEN_TOKENDATA_MISSING, "useridtoken " + userIdTokenJO.toString()) .setMasterToken(masterToken); try { signature = Base64.decode(userIdTokenJO.getString(KEY_SIGNATURE)); } catch (final IllegalArgumentException e) { throw new MslEncodingException( MslError.USERIDTOKEN_SIGNATURE_INVALID, "useridtoken " + userIdTokenJO.toString(), e) .setMasterToken(masterToken); } verified = cryptoContext.verify(tokendata, signature); } catch (final JSONException e) { throw new MslEncodingException( MslError.JSON_PARSE_ERROR, "useridtoken " + userIdTokenJO.toString(), e) .setMasterToken(masterToken); } // Pull the token data. final String tokenDataJson = new String(tokendata, MslConstants.DEFAULT_CHARSET); try { final JSONObject tokenDataJO = new JSONObject(tokenDataJson); renewalWindow = tokenDataJO.getLong(KEY_RENEWAL_WINDOW); expiration = tokenDataJO.getLong(KEY_EXPIRATION); if (expiration < renewalWindow) throw new MslException( MslError.USERIDTOKEN_EXPIRES_BEFORE_RENEWAL, "usertokendata " + tokenDataJson) .setMasterToken(masterToken); mtSerialNumber = tokenDataJO.getLong(KEY_MASTER_TOKEN_SERIAL_NUMBER); if (mtSerialNumber < 0 || mtSerialNumber > MslConstants.MAX_LONG_VALUE) throw new MslException( MslError.USERIDTOKEN_MASTERTOKEN_SERIAL_NUMBER_OUT_OF_RANGE, "usertokendata " + tokenDataJson) .setMasterToken(masterToken); serialNumber = tokenDataJO.getLong(KEY_SERIAL_NUMBER); if (serialNumber < 0 || serialNumber > MslConstants.MAX_LONG_VALUE) throw new MslException( MslError.USERIDTOKEN_SERIAL_NUMBER_OUT_OF_RANGE, "usertokendata " + tokenDataJson) .setMasterToken(masterToken); final byte[] ciphertext; try { ciphertext = Base64.decode(tokenDataJO.getString(KEY_USERDATA)); } catch (final IllegalArgumentException e) { throw new MslException( MslError.USERIDTOKEN_USERDATA_INVALID, tokenDataJO.getString(KEY_USERDATA)) .setMasterToken(masterToken); } if (ciphertext == null || ciphertext.length == 0) throw new MslException( MslError.USERIDTOKEN_USERDATA_MISSING, tokenDataJO.getString(KEY_USERDATA)) .setMasterToken(masterToken); userdata = (verified) ? cryptoContext.decrypt(ciphertext) : null; } catch (final JSONException e) { throw new MslEncodingException( MslError.USERIDTOKEN_TOKENDATA_PARSE_ERROR, "usertokendata " + tokenDataJson, e) .setMasterToken(masterToken); } catch (final MslCryptoException e) { e.setMasterToken(masterToken); throw e; } // Pull the user data. if (userdata != null) { final String userDataJson = new String(userdata, MslConstants.DEFAULT_CHARSET); try { final JSONObject userDataJO = new JSONObject(userDataJson); issuerData = (userDataJO.has(KEY_ISSUER_DATA)) ? userDataJO.getJSONObject(KEY_ISSUER_DATA) : null; final String identity = userDataJO.getString(KEY_IDENTITY); if (identity == null || identity.length() == 0) throw new MslException(MslError.USERIDTOKEN_IDENTITY_INVALID, "userdata " + userDataJson) .setMasterToken(masterToken); final TokenFactory factory = ctx.getTokenFactory(); user = factory.createUser(ctx, identity); if (user == null) throw new MslInternalException( "TokenFactory.createUser() returned null in violation of the interface contract."); } catch (final JSONException e) { throw new MslEncodingException( MslError.USERIDTOKEN_USERDATA_PARSE_ERROR, "userdata " + userDataJson, e) .setMasterToken(masterToken); } } else { issuerData = null; user = null; } // Verify serial numbers. if (masterToken == null || this.mtSerialNumber != masterToken.getSerialNumber()) throw new MslException( MslError.USERIDTOKEN_MASTERTOKEN_MISMATCH, "uit mtserialnumber " + this.mtSerialNumber + "; mt " + masterToken) .setMasterToken(masterToken); }
/** * 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; } }