From 42cb38380499e8c70f7ba52c869937fa1c066f49 Mon Sep 17 00:00:00 2001 From: ayyoob Date: Thu, 11 May 2017 21:21:53 +0530 Subject: [PATCH] auto healing in case of app deletion and added device scope to handle multiple session with same user --- .../APIManagementProviderServiceImpl.java | 185 ++++++++-------- .../app/modules/oauth/token-handler-utils.js | 36 ++- .../app/modules/oauth/token-handlers.js | 25 ++- .../oauth/token-protected-service-invokers.js | 38 +++- .../devicemgt/app/modules/utility.js | 206 ++++++++++++++++++ 5 files changed, 386 insertions(+), 104 deletions(-) diff --git a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java index bc92961f64..7f3def1ccd 100644 --- a/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java +++ b/components/apimgt-extensions/org.wso2.carbon.apimgt.application.extension/src/main/java/org/wso2/carbon/apimgt/application/extension/APIManagementProviderServiceImpl.java @@ -84,109 +84,118 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe String keyType, String username, boolean isAllowedAllDomains, String validityTime) throws APIManagerException { - StoreClient storeClient = APIApplicationManagerExtensionDataHolder.getInstance().getIntegrationClientService() - .getStoreClient(); + StoreClient storeClient = + APIApplicationManagerExtensionDataHolder.getInstance().getIntegrationClientService() + .getStoreClient(); String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext() .getTenantDomain(); + try { + ApplicationList applicationList = storeClient.getApplications() + .applicationsGet("", applicationName, 1, 0, CONTENT_TYPE, null); + Application application; + if (applicationList == null || applicationList.getList() == null || applicationList.getList().size() == 0) { + //create application; + application = new Application(); + application.setName(applicationName); + application.setSubscriber(username); + application.setDescription(""); + application.setThrottlingTier(ApiApplicationConstants.DEFAULT_TIER); + application.setGroupId(""); + application = storeClient.getIndividualApplication().applicationsPost(application, CONTENT_TYPE); + } else { + ApplicationInfo applicationInfo = applicationList.getList().get(0); + application = storeClient.getIndividualApplication() + .applicationsApplicationIdGet(applicationInfo.getApplicationId(), CONTENT_TYPE, null, null); + } + if (application == null) { + throw new APIManagerException( + "Api application creation failed for " + applicationName + " to the user " + username); + } - ApplicationList applicationList = storeClient.getApplications() - .applicationsGet("", applicationName, 1, 0, CONTENT_TYPE, null); - Application application; - if (applicationList == null || applicationList.getList() == null || applicationList.getList().size() == 0) { - //create application; - application = new Application(); - application.setName(applicationName); - application.setSubscriber(username); - application.setDescription(""); - application.setThrottlingTier(ApiApplicationConstants.DEFAULT_TIER); - application.setGroupId(""); - application = storeClient.getIndividualApplication().applicationsPost(application, CONTENT_TYPE); - } else { - ApplicationInfo applicationInfo = applicationList.getList().get(0); - application = storeClient.getIndividualApplication() - .applicationsApplicationIdGet(applicationInfo.getApplicationId(), CONTENT_TYPE, null, null); - } - if (application == null) { - throw new APIManagerException ( - "Api application creation failed for " + applicationName + " to the user " + username); - } - - SubscriptionList subscriptionList = storeClient.getSubscriptions().subscriptionsGet - (null, application.getApplicationId(), "", 0, 100, CONTENT_TYPE, null); - List needToSubscribe = new ArrayList<>(); - // subscribe to apis. - if (tags != null && tags.length > 0) { - for (String tag: tags) { - APIList apiList = storeClient.getApis().apisGet(MAX_API_PER_TAG, 0, tenantDomain, "tag:" + tag - , CONTENT_TYPE, null); - if (apiList.getList() == null || apiList.getList().size() == 0) { - apiList = storeClient.getApis().apisGet(MAX_API_PER_TAG, 0 - , MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, "tag:" + tag, CONTENT_TYPE, null); - } + SubscriptionList subscriptionList = storeClient.getSubscriptions().subscriptionsGet + (null, application.getApplicationId(), "", 0, 100, CONTENT_TYPE, null); + List needToSubscribe = new ArrayList<>(); + // subscribe to apis. + if (tags != null && tags.length > 0) { + for (String tag : tags) { + APIList apiList = storeClient.getApis().apisGet(MAX_API_PER_TAG, 0, tenantDomain, "tag:" + tag + , CONTENT_TYPE, null); + if (apiList.getList() == null || apiList.getList().size() == 0) { + apiList = storeClient.getApis().apisGet(MAX_API_PER_TAG, 0 + , MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, "tag:" + tag, CONTENT_TYPE, null); + } - if (apiList.getList() != null && apiList.getList().size() > 0) { - for (APIInfo apiInfo : apiList.getList()) { - String id = apiInfo.getProvider().replace("@", "-AT-") - + "-" + apiInfo.getName()+ "-" + apiInfo.getVersion(); - boolean subscriptionExist = false; - if (subscriptionList.getList() != null && subscriptionList.getList().size() > 0) { - for (Subscription subs : subscriptionList.getList()) { - if (subs.getApiIdentifier().equals(id)) { - subscriptionExist = true; - break; + if (apiList.getList() != null && apiList.getList().size() > 0) { + for (APIInfo apiInfo : apiList.getList()) { + String id = apiInfo.getProvider().replace("@", "-AT-") + + "-" + apiInfo.getName() + "-" + apiInfo.getVersion(); + boolean subscriptionExist = false; + if (subscriptionList.getList() != null && subscriptionList.getList().size() > 0) { + for (Subscription subs : subscriptionList.getList()) { + if (subs.getApiIdentifier().equals(id)) { + subscriptionExist = true; + break; + } } } - } - if (!subscriptionExist) { - Subscription subscription = new Subscription(); - //fix for APIMANAGER-5566 admin-AT-tenant1.com-Tenant1API1-1.0.0 - - subscription.setApiIdentifier(id); - subscription.setApplicationId(application.getApplicationId()); - subscription.tier(ApiApplicationConstants.DEFAULT_TIER); - if (!needToSubscribe.contains(subscription)){ - needToSubscribe.add(subscription); + if (!subscriptionExist) { + Subscription subscription = new Subscription(); + //fix for APIMANAGER-5566 admin-AT-tenant1.com-Tenant1API1-1.0.0 + + subscription.setApiIdentifier(id); + subscription.setApplicationId(application.getApplicationId()); + subscription.tier(ApiApplicationConstants.DEFAULT_TIER); + if (!needToSubscribe.contains(subscription)) { + needToSubscribe.add(subscription); + } } } } } } - } - if (!needToSubscribe.isEmpty()) { - storeClient.getSubscriptionMultitpleApi().subscriptionsMultiplePost(needToSubscribe, CONTENT_TYPE); - } - //end of subscription - - List applicationKeys = application.getKeys(); - if (applicationKeys != null) { - for (ApplicationKey applicationKey : applicationKeys) { - if (keyType.equals(applicationKey.getKeyType().toString())) { - ApiApplicationKey apiApplicationKey = new ApiApplicationKey(); - apiApplicationKey.setConsumerKey(applicationKey.getConsumerKey()); - apiApplicationKey.setConsumerSecret(applicationKey.getConsumerSecret()); - return apiApplicationKey; + if (!needToSubscribe.isEmpty()) { + storeClient.getSubscriptionMultitpleApi().subscriptionsMultiplePost(needToSubscribe, CONTENT_TYPE); + } + //end of subscription + + List applicationKeys = application.getKeys(); + if (applicationKeys != null) { + for (ApplicationKey applicationKey : applicationKeys) { + if (keyType.equals(applicationKey.getKeyType().toString())) { + if (applicationKey.getConsumerKey() != null && !applicationKey.getConsumerKey().isEmpty()) { + ApiApplicationKey apiApplicationKey = new ApiApplicationKey(); + apiApplicationKey.setConsumerKey(applicationKey.getConsumerKey()); + apiApplicationKey.setConsumerSecret(applicationKey.getConsumerSecret()); + return apiApplicationKey; + } + } } } - } - ApplicationKeyGenerateRequest applicationKeyGenerateRequest = new ApplicationKeyGenerateRequest(); - List allowedDomains = new ArrayList<>(); - if (isAllowedAllDomains) { - allowedDomains.add(ApiApplicationConstants.ALLOWED_DOMAINS); - } else { - allowedDomains.add(APIManagerUtil.getTenantDomain()); + ApplicationKeyGenerateRequest applicationKeyGenerateRequest = new ApplicationKeyGenerateRequest(); + List allowedDomains = new ArrayList<>(); + if (isAllowedAllDomains) { + allowedDomains.add(ApiApplicationConstants.ALLOWED_DOMAINS); + } else { + allowedDomains.add(APIManagerUtil.getTenantDomain()); + } + applicationKeyGenerateRequest.setAccessAllowDomains(allowedDomains); + applicationKeyGenerateRequest.setCallbackUrl(""); + applicationKeyGenerateRequest.setKeyType(ApplicationKeyGenerateRequest.KeyTypeEnum.PRODUCTION); + applicationKeyGenerateRequest.setValidityTime(validityTime); + + ApplicationKey applicationKey = storeClient.getIndividualApplication().applicationsGenerateKeysPost( + application.getApplicationId(), applicationKeyGenerateRequest, CONTENT_TYPE, null, null); + if (applicationKey.getConsumerKey() != null && !applicationKey.getConsumerKey().isEmpty()) { + ApiApplicationKey apiApplicationKey = new ApiApplicationKey(); + apiApplicationKey.setConsumerKey(applicationKey.getConsumerKey()); + apiApplicationKey.setConsumerSecret(applicationKey.getConsumerSecret()); + return apiApplicationKey; + } + throw new APIManagerException("Failed to generate keys for tenant: " + tenantDomain); + } catch (FeignException e) { + throw new APIManagerException("Failed to create api application for tenant: " + tenantDomain, e); } - applicationKeyGenerateRequest.setAccessAllowDomains(allowedDomains); - applicationKeyGenerateRequest.setCallbackUrl(""); - applicationKeyGenerateRequest.setKeyType(ApplicationKeyGenerateRequest.KeyTypeEnum.PRODUCTION); - applicationKeyGenerateRequest.setValidityTime(validityTime); - - ApplicationKey applicationKey = storeClient.getIndividualApplication().applicationsGenerateKeysPost( - application.getApplicationId(), applicationKeyGenerateRequest, CONTENT_TYPE, null, null); - ApiApplicationKey apiApplicationKey = new ApiApplicationKey(); - apiApplicationKey.setConsumerKey(applicationKey.getConsumerKey()); - apiApplicationKey.setConsumerSecret(applicationKey.getConsumerSecret()); - return apiApplicationKey; } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-handler-utils.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-handler-utils.js index 109e67f7ac..72f7739966 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-handler-utils.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-handler-utils.js @@ -23,6 +23,7 @@ var utils = function () { var constants = require("/app/modules/constants.js"); var carbon = require("carbon"); var authModule = require("/lib/modules/auth/auth.js").module; + var utility = require('/app/modules/utility.js').utility; //noinspection JSUnresolvedVariable var Base64 = Packages.org.apache.commons.codec.binary.Base64; @@ -297,11 +298,17 @@ var utils = function () { // returning access token by JWT grant type var tokenInfo = jwtClient.getAccessToken(encodedClientAppCredentials, endUsername, scopes); - var tokenData = {}; - tokenData["accessToken"] = tokenInfo.getAccessToken(); - tokenData["refreshToken"] = tokenInfo.getRefreshToken(); - tokenData["scopes"] = tokenInfo.getScopes(); - return tokenData; + if (tokenInfo) { + var tokenData = {}; + tokenData["accessToken"] = tokenInfo.getAccessToken(); + tokenData["refreshToken"] = tokenInfo.getRefreshToken(); + tokenData["scopes"] = tokenInfo.getScopes(); + return tokenData; + } else { + log.error("{/app/modules/oauth/token-handler-utils.js} Error in retrieving access token " + + "by jwt grant type - getTokenPairAndScopesByJWTGrantType()"); + return null; + } } }; @@ -378,5 +385,24 @@ var utils = function () { } }; + publicMethods["removeClientAppCredentials"] = function (tenantDomain) { + var cachedTenantBasedClientAppCredentialsMap = application.get(constants["CACHED_CREDENTIALS"]); + if (cachedTenantBasedClientAppCredentialsMap) { + if (cachedTenantBasedClientAppCredentialsMap[tenantDomain]) { + delete cachedTenantBasedClientAppCredentialsMap[tenantDomain]; + } + } + }; + + publicMethods["getUniqueBrowserScope"] = function () { + var deviceScope = "device_" + utility.md5(request.getHeader("User-Agent") + "::" + request.getRemoteAddr()); + deviceScope = deviceScope + " "; + log.error("device scope"); + log.error(deviceScope); + return deviceScope; + }; + + + return publicMethods; }(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-handlers.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-handlers.js index 0fa1fbb0dc..921d708c60 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-handlers.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-handlers.js @@ -51,7 +51,7 @@ var handlers = function () { // tokenPair will include current access token as well as current refresh token var arrayOfScopes = devicemgtProps["scopes"]; arrayOfScopes = arrayOfScopes.concat(utility.getDeviceTypesScopesList()); - var stringOfScopes = ""; + var stringOfScopes = tokenUtil.getUniqueBrowserScope(); arrayOfScopes.forEach(function (entry) { stringOfScopes += entry + " "; }); @@ -94,7 +94,7 @@ var handlers = function () { var tokenData; var arrayOfScopes = devicemgtProps["scopes"]; arrayOfScopes = arrayOfScopes.concat(utility.getDeviceTypesScopesList()); - var stringOfScopes = ""; + var stringOfScopes = tokenUtil.getUniqueBrowserScope(); arrayOfScopes.forEach(function (entry) { stringOfScopes += entry + " "; }); @@ -139,7 +139,7 @@ var handlers = function () { var tokenData; var arrayOfScopes = devicemgtProps["scopes"]; arrayOfScopes = arrayOfScopes.concat(utility.getDeviceTypesScopesList()); - var stringOfScopes = ""; + var stringOfScopes = tokenUtil.getUniqueBrowserScope(); arrayOfScopes.forEach(function (entry) { stringOfScopes += entry + " "; }); @@ -148,8 +148,7 @@ var handlers = function () { tokenData = tokenUtil. getTokenPairAndScopesByJWTGrantType(samlToken, encodedClientAppCredentials, stringOfScopes); if (!tokenData) { - throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up token " + - "pair by password grant type. Error in token " + + throw new Error("{/app/modules/oauth/token-handlers.js} Could not set up token. Error in token " + "retrieval - setupTokenPairBySamlGrantType(x, y)"); } else { var tokenPair = {}; @@ -180,6 +179,9 @@ var handlers = function () { if (!newTokenPair) { log.error("{/app/modules/oauth/token-handlers.js} Error in refreshing token pair. " + "Unable to update session context with new access token pair - refreshTokenPair()"); + userModule.logout(function () { + response.sendRedirect(devicemgtProps["appContext"] + "login"); + }); } else { session.put(constants["TOKEN_PAIR"], stringify(newTokenPair)); } @@ -263,5 +265,18 @@ var handlers = function () { } }; + publicMethods["removeClientDetails"] = function () { + var user = session.get(constants.USER_SESSION_KEY); + if (!user) { + log.error("User object was not found in the session"); + throw constants.ERRORS.USER_NOT_FOUND; + } + tokenUtil.removeClientAppCredentials(user.domain); + session.remove(constants["ENCODED_TENANT_BASED_WEB_SOCKET_CLIENT_CREDENTIALS"]); + session.remove(constants["ENCODED_TENANT_BASED_CLIENT_APP_CREDENTIALS"]); + session.remove(constants["TOKEN_PAIR"]); + session.remove(constants["ALLOWED_SCOPES"]); + }; + return publicMethods; }(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-protected-service-invokers.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-protected-service-invokers.js index ed40ee7de8..efcb3c6cae 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-protected-service-invokers.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/oauth/token-protected-service-invokers.js @@ -122,7 +122,12 @@ var invokers = function () { xmlHttpRequest.responseText == TOKEN_INVALID ) && count < 5) { tokenUtil.refreshTokenPair(); return privateMethods.execute(httpMethod, requestPayload, endpoint, responseCallback, ++count, headers); - } else if (privateMethods.isInvalidCredential(xmlHttpRequest.responseText)) { + } else if (privateMethods.isInvalidClientCredential(xmlHttpRequest.responseText)) { + log.error("API application has been removed."); + tokenUtil.removeClientDetails(); + session.invalidate(); + response.sendRedirect(devicemgtProps["appContext"] + "login"); + } else if (privateMethods.isInvalidCredential(xmlHttpRequest.responseText)) { tokenUtil.refreshTokenPair(); return privateMethods.execute(httpMethod, requestPayload, endpoint, responseCallback, ++count, headers); } @@ -143,11 +148,11 @@ var invokers = function () { if (responsePayload) { try { payload = parse(responsePayload); - if (payload["fault"]["code"] == 900901) { - log.debug("Access token is invalid: " + payload["fault"]["code"]); - log.debug(payload["fault"]["description"]); - return true; - } + if (payload["fault"]["code"] == 900901) { + log.debug("Access token is invalid: " + payload["fault"]["code"]); + log.debug(payload["fault"]["description"]); + return true; + } } catch (err) { // do nothing } @@ -155,6 +160,27 @@ var invokers = function () { return false; }; + /** + * This method verify whether the client credential is removed/blocked using response payload. + * This is required when using API gateway. + * @param responsePayload response payload. + * return true if it is invalid otherwise false. + */ + privateMethods["isInvalidClientCredential"] = + function (responsePayload) { + if (responsePayload) { + try { + payload = parse(responsePayload); + if (payload["fault"]["message"] == "Invalid Credentials") { + return true; + } + } catch (err) { + // do nothing + } + } + return false; + }; + /** * This method add Oauth authentication header to outgoing XML-HTTP Requests if Oauth authentication is enabled. * @param httpMethod HTTP request type. diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/utility.js b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/utility.js index 5505219181..ff8fb6ea2d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/utility.js +++ b/components/device-mgt/org.wso2.carbon.device.mgt.ui/src/main/resources/jaggeryapps/devicemgt/app/modules/utility.js @@ -180,5 +180,211 @@ utility = function () { } }; + publicMethods.md5 = function (s) { + function L(k, d) { + return (k << d) | (k >>> (32 - d)) + } + + function K(G, k) { + var I, d, F, H, x; + F = (G & 2147483648); + H = (k & 2147483648); + I = (G & 1073741824); + d = (k & 1073741824); + x = (G & 1073741823) + (k & 1073741823); + if (I & d) { + return (x ^ 2147483648 ^ F ^ H) + } + if (I | d) { + if (x & 1073741824) { + return (x ^ 3221225472 ^ F ^ H) + } else { + return (x ^ 1073741824 ^ F ^ H) + } + } else { + return (x ^ F ^ H) + } + } + + function r(d, F, k) { + return (d & F) | ((~d) & k) + } + + function q(d, F, k) { + return (d & k) | (F & (~k)) + } + + function p(d, F, k) { + return (d ^ F ^ k) + } + + function n(d, F, k) { + return (F ^ (d | (~k))) + } + + function u(G, F, aa, Z, k, H, I) { + G = K(G, K(K(r(F, aa, Z), k), I)); + return K(L(G, H), F) + } + + function f(G, F, aa, Z, k, H, I) { + G = K(G, K(K(q(F, aa, Z), k), I)); + return K(L(G, H), F) + } + + function D(G, F, aa, Z, k, H, I) { + G = K(G, K(K(p(F, aa, Z), k), I)); + return K(L(G, H), F) + } + + function t(G, F, aa, Z, k, H, I) { + G = K(G, K(K(n(F, aa, Z), k), I)); + return K(L(G, H), F) + } + + function e(G) { + var Z; + var F = G.length; + var x = F + 8; + var k = (x - (x % 64)) / 64; + var I = (k + 1) * 16; + var aa = Array(I - 1); + var d = 0; + var H = 0; + while (H < F) { + Z = (H - (H % 4)) / 4; + d = (H % 4) * 8; + aa[Z] = (aa[Z] | (G.charCodeAt(H) << d)); + H++ + } + Z = (H - (H % 4)) / 4; + d = (H % 4) * 8; + aa[Z] = aa[Z] | (128 << d); + aa[I - 2] = F << 3; + aa[I - 1] = F >>> 29; + return aa + } + + function B(x) { + var k = "", F = "", G, d; + for (d = 0; d <= 3; d++) { + G = (x >>> (d * 8)) & 255; + F = "0" + G.toString(16); + k = k + F.substr(F.length - 2, 2) + } + return k + } + + function J(k) { + k = k.replace(/rn/g, "n"); + var d = ""; + for (var F = 0; F < k.length; F++) { + var x = k.charCodeAt(F); + if (x < 128) { + d += String.fromCharCode(x) + } else { + if ((x > 127) && (x < 2048)) { + d += String.fromCharCode((x >> 6) | 192); + d += String.fromCharCode((x & 63) | 128) + } else { + d += String.fromCharCode((x >> 12) | 224); + d += String.fromCharCode(((x >> 6) & 63) | 128); + d += String.fromCharCode((x & 63) | 128) + } + } + } + return d + } + + var C = Array(); + var P, h, E, v, g, Y, X, W, V; + var S = 7, Q = 12, N = 17, M = 22; + var A = 5, z = 9, y = 14, w = 20; + var o = 4, m = 11, l = 16, j = 23; + var U = 6, T = 10, R = 15, O = 21; + s = J(s); + C = e(s); + Y = 1732584193; + X = 4023233417; + W = 2562383102; + V = 271733878; + for (P = 0; P < C.length; P += 16) { + h = Y; + E = X; + v = W; + g = V; + Y = u(Y, X, W, V, C[P + 0], S, 3614090360); + V = u(V, Y, X, W, C[P + 1], Q, 3905402710); + W = u(W, V, Y, X, C[P + 2], N, 606105819); + X = u(X, W, V, Y, C[P + 3], M, 3250441966); + Y = u(Y, X, W, V, C[P + 4], S, 4118548399); + V = u(V, Y, X, W, C[P + 5], Q, 1200080426); + W = u(W, V, Y, X, C[P + 6], N, 2821735955); + X = u(X, W, V, Y, C[P + 7], M, 4249261313); + Y = u(Y, X, W, V, C[P + 8], S, 1770035416); + V = u(V, Y, X, W, C[P + 9], Q, 2336552879); + W = u(W, V, Y, X, C[P + 10], N, 4294925233); + X = u(X, W, V, Y, C[P + 11], M, 2304563134); + Y = u(Y, X, W, V, C[P + 12], S, 1804603682); + V = u(V, Y, X, W, C[P + 13], Q, 4254626195); + W = u(W, V, Y, X, C[P + 14], N, 2792965006); + X = u(X, W, V, Y, C[P + 15], M, 1236535329); + Y = f(Y, X, W, V, C[P + 1], A, 4129170786); + V = f(V, Y, X, W, C[P + 6], z, 3225465664); + W = f(W, V, Y, X, C[P + 11], y, 643717713); + X = f(X, W, V, Y, C[P + 0], w, 3921069994); + Y = f(Y, X, W, V, C[P + 5], A, 3593408605); + V = f(V, Y, X, W, C[P + 10], z, 38016083); + W = f(W, V, Y, X, C[P + 15], y, 3634488961); + X = f(X, W, V, Y, C[P + 4], w, 3889429448); + Y = f(Y, X, W, V, C[P + 9], A, 568446438); + V = f(V, Y, X, W, C[P + 14], z, 3275163606); + W = f(W, V, Y, X, C[P + 3], y, 4107603335); + X = f(X, W, V, Y, C[P + 8], w, 1163531501); + Y = f(Y, X, W, V, C[P + 13], A, 2850285829); + V = f(V, Y, X, W, C[P + 2], z, 4243563512); + W = f(W, V, Y, X, C[P + 7], y, 1735328473); + X = f(X, W, V, Y, C[P + 12], w, 2368359562); + Y = D(Y, X, W, V, C[P + 5], o, 4294588738); + V = D(V, Y, X, W, C[P + 8], m, 2272392833); + W = D(W, V, Y, X, C[P + 11], l, 1839030562); + X = D(X, W, V, Y, C[P + 14], j, 4259657740); + Y = D(Y, X, W, V, C[P + 1], o, 2763975236); + V = D(V, Y, X, W, C[P + 4], m, 1272893353); + W = D(W, V, Y, X, C[P + 7], l, 4139469664); + X = D(X, W, V, Y, C[P + 10], j, 3200236656); + Y = D(Y, X, W, V, C[P + 13], o, 681279174); + V = D(V, Y, X, W, C[P + 0], m, 3936430074); + W = D(W, V, Y, X, C[P + 3], l, 3572445317); + X = D(X, W, V, Y, C[P + 6], j, 76029189); + Y = D(Y, X, W, V, C[P + 9], o, 3654602809); + V = D(V, Y, X, W, C[P + 12], m, 3873151461); + W = D(W, V, Y, X, C[P + 15], l, 530742520); + X = D(X, W, V, Y, C[P + 2], j, 3299628645); + Y = t(Y, X, W, V, C[P + 0], U, 4096336452); + V = t(V, Y, X, W, C[P + 7], T, 1126891415); + W = t(W, V, Y, X, C[P + 14], R, 2878612391); + X = t(X, W, V, Y, C[P + 5], O, 4237533241); + Y = t(Y, X, W, V, C[P + 12], U, 1700485571); + V = t(V, Y, X, W, C[P + 3], T, 2399980690); + W = t(W, V, Y, X, C[P + 10], R, 4293915773); + X = t(X, W, V, Y, C[P + 1], O, 2240044497); + Y = t(Y, X, W, V, C[P + 8], U, 1873313359); + V = t(V, Y, X, W, C[P + 15], T, 4264355552); + W = t(W, V, Y, X, C[P + 6], R, 2734768916); + X = t(X, W, V, Y, C[P + 13], O, 1309151649); + Y = t(Y, X, W, V, C[P + 4], U, 4149444226); + V = t(V, Y, X, W, C[P + 11], T, 3174756917); + W = t(W, V, Y, X, C[P + 2], R, 718787259); + X = t(X, W, V, Y, C[P + 9], O, 3951481745); + Y = K(Y, h); + X = K(X, E); + W = K(W, v); + V = K(V, g) + } + var i = B(Y) + B(X) + B(W) + B(V); + return i.toLowerCase() + }; + return publicMethods; }();