auto healing in case of app deletion and added device scope to handle multiple session with same user

4.x.x
ayyoob 8 years ago
parent 84d305dcd4
commit 42cb383804

@ -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<Subscription> 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<Subscription> 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<ApplicationKey> 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<ApplicationKey> 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<String> allowedDomains = new ArrayList<>();
if (isAllowedAllDomains) {
allowedDomains.add(ApiApplicationConstants.ALLOWED_DOMAINS);
} else {
allowedDomains.add(APIManagerUtil.getTenantDomain());
ApplicationKeyGenerateRequest applicationKeyGenerateRequest = new ApplicationKeyGenerateRequest();
List<String> 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;
}
}

@ -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;
}();

@ -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;
}();

@ -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.

@ -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;
}();

Loading…
Cancel
Save