/* * oxAuth is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. * * Copyright (c) 2014, Gluu */ package org.xdi.oxauth.model.crypto; import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.gluu.oxeleven.model.JwksRequestParam; import org.gluu.oxeleven.model.KeyRequestParam; import org.xdi.oxauth.model.configuration.AppConfiguration; import org.xdi.oxauth.model.crypto.signature.SignatureAlgorithm; import org.xdi.oxauth.model.crypto.signature.SignatureAlgorithmFamily; import org.xdi.oxauth.model.jwk.JSONWebKey; import org.xdi.oxauth.model.jwk.JSONWebKeySet; import org.xdi.oxauth.model.util.Base64Util; import sun.security.rsa.RSAPublicKeyImpl; import java.math.BigInteger; import java.security.AlgorithmParameters; import java.security.KeyFactory; import java.security.PublicKey; import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.ECPublicKeySpec; import java.util.ArrayList; import java.util.GregorianCalendar; import java.util.TimeZone; import static org.xdi.oxauth.model.jwk.JWKParameter.*; /** * @author Javier Rojas Blum * @version August 17, 2016 */ public abstract class AbstractCryptoProvider { public abstract JSONObject generateKey(SignatureAlgorithm signatureAlgorithm, Long expirationTime) throws Exception; public abstract String sign(String signingInput, String keyId, String sharedSecret, SignatureAlgorithm signatureAlgorithm) throws Exception; public abstract boolean verifySignature(String signingInput, String encodedSignature, String keyId, JSONObject jwks, String sharedSecret, SignatureAlgorithm signatureAlgorithm) throws Exception; public abstract boolean deleteKey(String keyId) throws Exception; public String getKeyId(JSONWebKeySet jsonWebKeySet, SignatureAlgorithm signatureAlgorithm) throws Exception { for (JSONWebKey key : jsonWebKeySet.getKeys()) { if (signatureAlgorithm == key.getAlg()) { return key.getKid(); } } return null; } public JwksRequestParam getJwksRequestParam(JSONObject jwkJsonObject) throws JSONException { JwksRequestParam jwks = new JwksRequestParam(); jwks.setKeyRequestParams(new ArrayList<KeyRequestParam>()); KeyRequestParam key = new KeyRequestParam(); key.setAlg(jwkJsonObject.getString(ALGORITHM)); key.setKid(jwkJsonObject.getString(KEY_ID)); key.setUse(jwkJsonObject.getString(KEY_USE)); key.setKty(jwkJsonObject.getString(KEY_TYPE)); key.setN(jwkJsonObject.optString(MODULUS)); key.setE(jwkJsonObject.optString(EXPONENT)); key.setCrv(jwkJsonObject.optString(CURVE)); key.setX(jwkJsonObject.optString(X)); key.setY(jwkJsonObject.optString(Y)); jwks.getKeyRequestParams().add(key); return jwks; } public static JSONObject generateJwks(int keyRegenerationInterval, int idTokenLifeTime, AppConfiguration configuration) throws Exception { JSONArray keys = new JSONArray(); GregorianCalendar expirationTime = new GregorianCalendar(TimeZone.getTimeZone("UTC")); expirationTime.add(GregorianCalendar.HOUR, keyRegenerationInterval); expirationTime.add(GregorianCalendar.SECOND, idTokenLifeTime); AbstractCryptoProvider cryptoProvider = CryptoProviderFactory.getCryptoProvider(configuration); try { keys.put(cryptoProvider.generateKey(SignatureAlgorithm.RS256, expirationTime.getTimeInMillis())); } catch (Exception ex) { } try { keys.put(cryptoProvider.generateKey(SignatureAlgorithm.RS384, expirationTime.getTimeInMillis())); } catch (Exception ex) { } try { keys.put(cryptoProvider.generateKey(SignatureAlgorithm.RS512, expirationTime.getTimeInMillis())); } catch (Exception ex) { } try { keys.put(cryptoProvider.generateKey(SignatureAlgorithm.ES256, expirationTime.getTimeInMillis())); } catch (Exception ex) { } try { keys.put(cryptoProvider.generateKey(SignatureAlgorithm.ES384, expirationTime.getTimeInMillis())); } catch (Exception ex) { } try { keys.put(cryptoProvider.generateKey(SignatureAlgorithm.ES512, expirationTime.getTimeInMillis())); } catch (Exception ex) { } JSONObject jsonObject = new JSONObject(); jsonObject.put(JSON_WEB_KEY_SET, keys); return jsonObject; } public PublicKey getPublicKey(String alias, JSONObject jwks) throws Exception { java.security.PublicKey publicKey = null; JSONArray webKeys = jwks.getJSONArray(JSON_WEB_KEY_SET); for (int i = 0; i < webKeys.length(); i++) { JSONObject key = webKeys.getJSONObject(i); if (alias.equals(key.getString(KEY_ID))) { SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.fromString(key.getString(ALGORITHM)); if (signatureAlgorithm != null) { if (signatureAlgorithm.getFamily().equals(SignatureAlgorithmFamily.RSA)) { publicKey = new RSAPublicKeyImpl( new BigInteger(1, Base64Util.base64urldecode(key.getString(MODULUS))), new BigInteger(1, Base64Util.base64urldecode(key.getString(EXPONENT)))); } else if (signatureAlgorithm.getFamily().equals(SignatureAlgorithmFamily.EC)) { AlgorithmParameters parameters = AlgorithmParameters.getInstance(SignatureAlgorithmFamily.EC); parameters.init(new ECGenParameterSpec(signatureAlgorithm.getCurve().getAlias())); ECParameterSpec ecParameters = parameters.getParameterSpec(ECParameterSpec.class); publicKey = KeyFactory.getInstance(SignatureAlgorithmFamily.EC).generatePublic(new ECPublicKeySpec( new ECPoint( new BigInteger(1, Base64Util.base64urldecode(key.getString(X))), new BigInteger(1, Base64Util.base64urldecode(key.getString(Y))) ), ecParameters)); } } } } return publicKey; } }