separate common

This commit is contained in:
MaxKey
2021-02-15 09:57:52 +08:00
parent d1d8924b60
commit 647d899771
221 changed files with 5038 additions and 203 deletions

View File

@@ -0,0 +1,3 @@
Manifest-Version: 1.0
Class-Path:

View File

@@ -0,0 +1,84 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* AbstractCache .
* @author Crystal
* @version 1.0
* @Date 2015/11/12
*/
public abstract class AbstractCache extends Thread {
protected static final Logger _logger = LoggerFactory.getLogger(AbstractCache.class);
private int interval = 30000 / 1000;
public AbstractCache() {
}
public abstract void business();
@Override
public void run() {
while (true) {
_logger.debug("Cache Thread Start run " + getName());
_logger.info("Cache Thread Start run " + this.getClass());
try {
business();
_logger.debug("Cache Thread " + getName() + " Finished . ");
_logger.info("Cache Thread " + this.getClass() + " Finished . ");
_logger.debug("Cache Thread sleep " + (interval * 1000) + " minute . ");
sleep(interval * 1000);
} catch (InterruptedException e) {
_logger.error(e.getMessage(), e);
}
}
}
@Override
public void start() {
this.run();
}
/**
* constructor.
* @param name String
*/
public AbstractCache(String name) {
super(name);
// TODO Auto-generated constructor stub
}
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.cache;
import java.util.ArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* CacheFactory.
* @author Crystal.Sea
*
*/
public class CacheFactory {
protected static final Logger _logger = LoggerFactory.getLogger(CacheFactory.class);
private ArrayList<AbstractCache> cache;
/**
* CacheFactory.
*/
public CacheFactory() {
}
/**
* start Cache.
*/
public void start() {
for (AbstractCache cacheable : cache) {
_logger.info("Cache " + cacheable.getClass());
new Thread(cacheable).start();
}
}
public ArrayList<AbstractCache> getCache() {
return cache;
}
public void setCache(ArrayList<AbstractCache> cache) {
this.cache = cache;
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
/**
* @author Administrator
*
*/
package org.maxkey.cache;

View File

@@ -0,0 +1,230 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.configuration;
import org.maxkey.constants.ConstantsProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
/**
* 全局应用程序配置 包含 1、数据源配置 dataSoruceConfig 2、字符集转换配置 characterEncodingConfig
* 3、webseal认证集成配置 webSealConfig 4、系统的配置 sysConfig 5、所有用户可访问地址配置 allAccessUrl
*
* 其中1、2、3项在applicationContext.xml中配置配置文件applicationConfig.properties
* 4项根据dynamic的属性判断是否动态从sysConfigService动态读取
*
* @author Crystal.Sea
*
*/
@Component
@PropertySource(ConstantsProperties.maxKeyPropertySource)
@PropertySource(ConstantsProperties.applicationPropertySource)
public class ApplicationConfig {
private static final Logger _logger = LoggerFactory.getLogger(ApplicationConfig.class);
@Autowired
EmailConfig emailConfig;
@Autowired
CharacterEncodingConfig characterEncodingConfig;
@Autowired
LoginConfig loginConfig;
@Value("${config.server.basedomain}")
String baseDomainName;
@Value("${config.server.domain}")
String domainName;
@Value("${config.server.name}")
String serverName;
@Value("${config.server.uri}")
String serverPrefix;
@Value("${config.server.default.uri}")
String defaultUri;
@Value("${config.server.management.uri}")
String managementUri;
@Value("${server.port:8080}")
private int port;
@Value("${config.identity.kafkasupport:false}")
private boolean kafkaSupport;
@Value("${config.maxkey.uri}")
private String maxKeyUri;
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public ApplicationConfig() {
super();
}
/**
* @return the characterEncodingConfig
*/
public CharacterEncodingConfig getCharacterEncodingConfig() {
return characterEncodingConfig;
}
/**
* @param characterEncodingConfig the characterEncodingConfig to set
*/
public void setCharacterEncodingConfig(CharacterEncodingConfig characterEncodingConfig) {
this.characterEncodingConfig = characterEncodingConfig;
}
public LoginConfig getLoginConfig() {
return loginConfig;
}
public void setLoginConfig(LoginConfig loginConfig) {
this.loginConfig = loginConfig;
}
public String getServerName() {
return serverName;
}
public void setServerName(String serverName) {
this.serverName = serverName;
}
public String getServerPrefix() {
return serverPrefix;
}
public void setServerPrefix(String serverPrefix) {
this.serverPrefix = serverPrefix;
}
/**
* @return the domainName
*/
public String getDomainName() {
return domainName;
}
/**
* @param domainName the domainName to set
*/
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public String getBaseDomainName() {
return baseDomainName;
}
public void setBaseDomainName(String baseDomainName) {
this.baseDomainName = baseDomainName;
}
/**
* @return the emailConfig
*/
public EmailConfig getEmailConfig() {
return emailConfig;
}
/**
* @param emailConfig the emailConfig to set
*/
public void setEmailConfig(EmailConfig emailConfig) {
this.emailConfig = emailConfig;
}
public String getManagementUri() {
return managementUri;
}
public void setManagementUri(String managementUri) {
this.managementUri = managementUri;
}
public String getDefaultUri() {
return defaultUri;
}
public void setDefaultUri(String defaultUri) {
this.defaultUri = defaultUri;
}
public boolean isKafkaSupport() {
return kafkaSupport;
}
public void setKafkaSupport(boolean kafkaSupport) {
this.kafkaSupport = kafkaSupport;
}
public String getMaxKeyUri() {
return maxKeyUri;
}
public void setMaxKeyUri(String maxKeyUri) {
this.maxKeyUri = maxKeyUri;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("ApplicationConfig [emailConfig=");
builder.append(emailConfig);
builder.append(", characterEncodingConfig=");
builder.append(characterEncodingConfig);
builder.append(", loginConfig=");
builder.append(loginConfig);
builder.append(", baseDomainName=");
builder.append(baseDomainName);
builder.append(", domainName=");
builder.append(domainName);
builder.append(", serverName=");
builder.append(serverName);
builder.append(", serverPrefix=");
builder.append(serverPrefix);
builder.append(", defaultUri=");
builder.append(defaultUri);
builder.append(", managementUri=");
builder.append(managementUri);
builder.append(", port=");
builder.append(port);
builder.append(", kafkaSupport=");
builder.append(kafkaSupport);
builder.append(", maxKeyUri=");
builder.append(maxKeyUri);
builder.append("]");
return builder.toString();
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.configuration;
import java.io.UnsupportedEncodingException;
import org.maxkey.constants.ConstantsProperties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* 字符集转换及转换配置.
*
* @author Crystal.Sea
*
*/
@Configuration
@PropertySource(ConstantsProperties.applicationPropertySource)
public class CharacterEncodingConfig {
/**
* 源字符集.
*/
@Value("${server.servlet.encoding.charset.from:UTF-8}")
String fromCharSet;
/**
* 目标字符集.
*/
@Value("${server.servlet.encoding.charset:UTF-8}")
String toCharSet;
/**
* 转换标志.
*/
@Value("${server.servlet.encoding.enabled:false}")
boolean encoding = false;
public CharacterEncodingConfig() {
}
public String getFromCharSet() {
return fromCharSet;
}
public void setFromCharSet(String fromCharSet) {
this.fromCharSet = fromCharSet;
}
public String getToCharSet() {
return toCharSet;
}
public void setToCharSet(String toCharSet) {
this.toCharSet = toCharSet;
}
public boolean isEncoding() {
return encoding;
}
public void setEncoding(boolean encoding) {
this.encoding = encoding;
}
/**
* 字符集转换.
*
* @param encodingString 源字符串
* @return encoded目标字符串
*/
public String encoding(String encodingString) {
if (!this.encoding || encodingString == null) {
return encodingString;
}
try {
return new String(encodingString.getBytes(this.fromCharSet), this.toCharSet);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("CharacterEncodingConfig [fromCharSet=");
builder.append(fromCharSet);
builder.append(", toCharSet=");
builder.append(toCharSet);
builder.append(", encoding=");
builder.append(encoding);
builder.append("]");
return builder.toString();
}
}

View File

@@ -0,0 +1,149 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.configuration;
import org.maxkey.constants.ConstantsProperties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource(ConstantsProperties.applicationPropertySource)
public class EmailConfig {
@Value("${spring.mail.username}")
private String username;
@Value("${spring.mail.password}")
private String password;
@Value("${spring.mail.host}")
private String smtpHost;
@Value("${spring.mail.port}")
private Integer port;
@Value("${spring.mail.properties.ssl}")
private boolean ssl;
@Value("${spring.mail.properties.sender}")
private String sender;
public EmailConfig() {
}
/*
* @return the username
*/
public String getUsername() {
return username;
}
/*
* @param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
/*
* @return the password
*/
public String getPassword() {
return password;
}
/*
* @param password the password to set
*/
public void setPassword(String password) {
this.password = password;
}
/*
* @return the smtpHost
*/
public String getSmtpHost() {
return smtpHost;
}
/*
* @param smtpHost the smtpHost to set
*/
public void setSmtpHost(String smtpHost) {
this.smtpHost = smtpHost;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
/*
* @return the port
*/
public Integer getPort() {
return port;
}
/*
* @param port the port to set
*/
public void setPort(Integer port) {
this.port = port;
}
/*
* @return the ssl
*/
public boolean isSsl() {
return ssl;
}
/*
* @param ssl the ssl to set
*/
public void setSsl(boolean ssl) {
this.ssl = ssl;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("EmailConfig [username=");
builder.append(username);
builder.append(", password=");
builder.append(password);
builder.append(", smtpHost=");
builder.append(smtpHost);
builder.append(", port=");
builder.append(port);
builder.append(", ssl=");
builder.append(ssl);
builder.append(", sender=");
builder.append(sender);
builder.append("]");
return builder.toString();
}
}

View File

@@ -0,0 +1,147 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.configuration;
import org.maxkey.constants.ConstantsProperties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource(ConstantsProperties.maxKeyPropertySource)
public class LoginConfig {
@Value("${config.login.captcha}")
boolean captcha;
//验证码类型 text 文本 arithmetic算术验证码
@Value("${config.login.captcha.type:text}")
String captchaType;
@Value("${config.login.mfa}")
boolean mfa;
@Value("${config.login.socialsignon}")
boolean socialSignOn;
@Value("${config.login.kerberos}")
boolean kerberos;
@Value("${config.login.remeberme}")
boolean remeberMe;
@Value("${config.login.wsfederation}")
boolean wsFederation;
@Value("${config.login.default.uri}")
String defaultUri;
/**
* .
*/
public LoginConfig() {
// TODO Auto-generated constructor stub
}
public boolean isCaptcha() {
return captcha;
}
public void setCaptcha(boolean captcha) {
this.captcha = captcha;
}
public boolean isSocialSignOn() {
return socialSignOn;
}
public void setSocialSignOn(boolean socialSignOn) {
this.socialSignOn = socialSignOn;
}
public boolean isKerberos() {
return kerberos;
}
public void setKerberos(boolean kerberos) {
this.kerberos = kerberos;
}
public boolean isMfa() {
return mfa;
}
public void setMfa(boolean mfa) {
this.mfa = mfa;
}
public String getDefaultUri() {
return defaultUri;
}
public void setDefaultUri(String defaultUri) {
this.defaultUri = defaultUri;
}
public boolean isRemeberMe() {
return remeberMe;
}
public void setRemeberMe(boolean remeberMe) {
this.remeberMe = remeberMe;
}
public boolean isWsFederation() {
return wsFederation;
}
public void setWsFederation(boolean wsFederation) {
this.wsFederation = wsFederation;
}
public String getCaptchaType() {
return captchaType;
}
public void setCaptchaType(String captchaType) {
this.captchaType = captchaType;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("LoginConfig [captcha=");
builder.append(captcha);
builder.append(", captchaType=");
builder.append(captchaType);
builder.append(", mfa=");
builder.append(mfa);
builder.append(", socialSignOn=");
builder.append(socialSignOn);
builder.append(", kerberos=");
builder.append(kerberos);
builder.append(", remeberMe=");
builder.append(remeberMe);
builder.append(", wsFederation=");
builder.append(wsFederation);
builder.append(", defaultUri=");
builder.append(defaultUri);
builder.append("]");
return builder.toString();
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.configuration.oidc;
import java.net.URI;
import java.util.Set;
public interface OIDCProviderMetadata {
public String getIssuer();
public void setIssuer(String issuer);
public URI getAuthorizationEndpoint();
public void setAuthorizationEndpoint(URI authorizationEndpoint);
public URI getTokenEndpoint();
public void setTokenEndpoint(URI tokenEndpoint);
public URI getUserinfoEndpoint();
public void setUserinfoEndpoint(URI userinfoEndpoint);
public URI getJwksUri();
public void setJwksUri(URI jwksUri);
public URI getRegistrationEndpoint();
public void setRegistrationEndpoint(URI registrationEndpoint);
public Set<String> getScopesSupported();
public void setScopesSupported(Set<String> scopesSupported);
public Set<String> getResponseTypesSupported();
public void setResponseTypesSupported(Set<String> responseTypesSupported);
}

View File

@@ -0,0 +1,151 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.configuration.oidc;
import java.net.URI;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
/**
* OIDCProviderMetadataDetails.
* @author cm
*
*/
public class OIDCProviderMetadataDetails implements OIDCProviderMetadata {
protected String issuer;
protected URI authorizationEndpoint;
protected URI tokenEndpoint;
protected URI userinfoEndpoint;
protected URI jwksUri;
protected URI registrationEndpoint;
protected Set<String> scopesSupported;
protected Set<String> responseTypesSupported;
public String getIssuer() {
return issuer;
}
public void setIssuer(String issuer) {
this.issuer = issuer;
}
public URI getAuthorizationEndpoint() {
return authorizationEndpoint;
}
public void setAuthorizationEndpoint(URI authorizationEndpoint) {
this.authorizationEndpoint = authorizationEndpoint;
}
public URI getTokenEndpoint() {
return tokenEndpoint;
}
public void setTokenEndpoint(URI tokenEndpoint) {
this.tokenEndpoint = tokenEndpoint;
}
public URI getUserinfoEndpoint() {
return userinfoEndpoint;
}
public void setUserinfoEndpoint(URI userinfoEndpoint) {
this.userinfoEndpoint = userinfoEndpoint;
}
public URI getJwksUri() {
return jwksUri;
}
public void setJwksUri(URI jwksUri) {
this.jwksUri = jwksUri;
}
public URI getRegistrationEndpoint() {
return registrationEndpoint;
}
public void setRegistrationEndpoint(URI registrationEndpoint) {
this.registrationEndpoint = registrationEndpoint;
}
public Set<String> getScopesSupported() {
return scopesSupported;
}
public void setScopesSupported(Set<String> scopesSupported) {
this.scopesSupported = scopesSupported;
}
public Set<String> getResponseTypesSupported() {
return responseTypesSupported;
}
public void setResponseTypesSupported(Set<String> responseTypesSupported) {
this.responseTypesSupported = responseTypesSupported;
}
@Override
public String toString() {
final int maxLen = 4;
StringBuilder builder = new StringBuilder();
builder.append("OIDCProviderMetadataDetails [issuer=");
builder.append(issuer);
builder.append(", authorizationEndpoint=");
builder.append(authorizationEndpoint);
builder.append(", tokenEndpoint=");
builder.append(tokenEndpoint);
builder.append(", userinfoEndpoint=");
builder.append(userinfoEndpoint);
builder.append(", jwksUri=");
builder.append(jwksUri);
builder.append(", registrationEndpoint=");
builder.append(registrationEndpoint);
builder.append(", scopesSupported=");
builder.append(scopesSupported != null ? toString(scopesSupported, maxLen) : null);
builder.append(", responseTypesSupported=");
builder.append(responseTypesSupported != null ? toString(responseTypesSupported, maxLen) : null);
builder.append("]");
return builder.toString();
}
private String toString(Collection<?> collection, int maxLen) {
StringBuilder builder = new StringBuilder();
builder.append("[");
int i = 0;
for (Iterator<?> iterator = collection.iterator(); iterator.hasNext() && i < maxLen; i++) {
if (i > 0)
builder.append(", ");
builder.append(iterator.next());
}
builder.append("]");
return builder.toString();
}
// TODO: Complete remaining properties from
// http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
/**
* Define int for boolean 0 false 1 true.
*
* @author Crystal.Sea
*
*/
public class Boolean {
public static final int FALSE = 0;
public static final int TRUE = 1;
private int value = FALSE;
public Boolean() {
}
public int getValue() {
return value;
}
public boolean isValue() {
return TRUE == value;
}
public void setValue(int value) {
this.value = value;
}
public static boolean isTrue(int value) {
return TRUE == value;
}
public static boolean isFalse(int value) {
return FALSE == value;
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
public class ConstantsEntryType {
public static int USERINFO_TYPE = 1;
public static int ORG_TYPE = 2;
public static int GROUP_TYPE = 3;
public static int PASSWORD_TYPE = 4;
public static int RESOURCES_TYPE = 5;
public static int PERMISSIONS_TYPE = 6;
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
public class ConstantsLoginType {
public static final String LOCAL = "Local Login";
public static final String BASIC = "Basic";
public static final String SOCIALSIGNON = "Social Sign On";
public static final String REMEBER_ME = "RemeberMe";
public static final String DESKTOP = "Desktop";
public static final String KERBEROS = "Kerberos";
public static final String SAMLTRUST = "SAML v2.0 Trust";
public static final String MSADTRUST = "MS AD Trust";
public static final String CAS = "CAS";
public static final String WSFEDERATION = "WsFederation";
public static final String JWT = "Jwt";
public static final String HTTPHEADER = "HttpHeader";
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
public final class ConstantsOperateAction {
public static final int CREATE_ACTION = 1;
public static final int DELETE_ACTION = 2;
public static final int UPDATE_ACTION = 3;
public static final int CHANGE_PASSWORD_ACTION = 4;
public static final int ADD_MEMBER_ACTION = 5;
public static final int DELETE_MEMBER_ACTION = 6;
public static final int VIEW_ACTION = 7;
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
public final class ConstantsOperateMessage {
public static final String INSERT_SUCCESS = "message.action.insert.success";
public static final String INSERT_ERROR = "message.action.insert.error";
public static final String UPDATE_SUCCESS = "message.action.update.success";
public static final String UPDATE_ERROR = "message.action.update.error";
public static final String DELETE_SUCCESS = "message.action.delete.success";
public static final String DELETE_ERROR = "message.action.delete.error";
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
/**
* PASSWORDSETTYPE.
* @author Crystal.Sea
*
*/
public final class ConstantsPasswordSetType {
public static final int PASSWORD_NORMAL = 0;
public static final int INITIAL_PASSWORD = 1;
public static final int MANAGER_CHANGED_PASSWORD = 2;
public static final int PASSWORD_EXPIRED = 3;
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
/**
* PROTOCOLS.
* @author Crystal.Sea
*
*/
public final class ConstantsPersistence {
public static final int INMEMORY = 0;
public static final int JDBC = 1;
public static final int REDIS = 2;
}

View File

@@ -0,0 +1,27 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
public final class ConstantsPlatformRole {
public static final String PLATFORM_ADMIN = "PLATFORM_ADMIN";
public static final String TANANT_ADMIN = "TANANT_ADMIN";
public static final String ORDINARY_USER = "ORDINARY_USER";
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
import org.junit.Test;
public class ConstantsProperties {
public static final String applicationPropertySource =
"classpath:/application.properties";
public static final String maxKeyPropertySource =
"classpath:/maxkey.properties";
public static final String kaptchaPropertySource =
"classpath:/kaptcha.properties";
public static String classPathResource(String propertySource) {
return propertySource.replaceAll("classpath:","");
}
@Test
public void classPathResourceTest() {
System.out.println(classPathResource(maxKeyPropertySource));
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
/**
* PROTOCOLS.
* @author Crystal.Sea
*
*/
public final class ConstantsProtocols {
public static final String DESKTOP = "Desktop";
public static final String BASIC = "Basic";
public static final String EXTEND_API = "Extend_API";
public static final String FORMBASED = "Form_Based";
public static final String TOKENBASED = "Token_Based";
// OAuth
public static final String OAUTH20 = "OAuth_v2.0";
// SAML
public static final String SAML20 = "SAML_v2.0";
public static final String OPEN_ID_CONNECT = "OpenID_Connect";
public static final String CAS = "CAS";
public static final String JWT = "JWT";
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
public final class ConstantsServiceMessage {
public static final class EMPLOYEES {
public static final String SERVICE_NAME = "employees";
public static final String XE00000001 = "XE00000001";
public static final String XE00000002 = "XE00000002";
public static final String XE00000003 = "XE00000003";
public static final String XE00000004 = "XE00000004";
public static final String XE00000005 = "XE00000005";
public static final String XE00000006 = "XE00000006";
public static final String XE00000007 = "XE00000007";
public static final String XE00000008 = "XE00000008";
public static final String XW00000001 = "XW00000001";
public static final String XW00000002 = "XW00000002";
public static final String XS00000001 = "XS00000001";
public static final String XS00000002 = "XS00000002";
public static final String XS00000003 = "XS00000003";
}
public static final class ENTERPRISES {
public static final String SERVICE_NAME = "enterprises";
public static final String XE00000001 = "XE00000001";
public static final String XE00000002 = "XE00000002";
public static final String XE00000003 = "XE00000003";
public static final String XE00000004 = "XE00000004";
public static final String XE00000005 = "XE00000005";
public static final String XE00000006 = "XE00000006";
public static final String XE00000007 = "XE00000007";
public static final String XE00000008 = "XE00000008";
public static final String XS00000001 = "XS00000001";
public static final String XS00000002 = "XS00000002";
public static final String XS00000003 = "XS00000003";
public static final String XS00000004 = "XS00000004";
}
public static final class RETRIEVEPASSWORD {
public static final String SERVICE_NAME = "retrievepassword";
public static final String XS00000001 = "XS00000001";
public static final String XS00000002 = "XS00000002";
public static final String XE00000001 = "XE00000001";
public static final String XE00000002 = "XE00000002";
public static final String XE00000003 = "XE00000003";
}
public static final class USERCENTER {
public static final String SERVICE_NAME = "usercenter";
public static final String XS00000001 = "XS00000001";
public static final String XS00000002 = "XS00000002";
public static final String XS00000003 = "XS00000003";
public static final String XE00000001 = "XE00000001";
public static final String XE00000002 = "XE00000002";
public static final String XE00000003 = "XE00000003";
}
public static final class APPLICATIONS {
public static final String SERVICE_NAME = "applications";
public static final String XS00000001 = "XS00000001";
public static final String XS00000002 = "XS00000002";
public static final String XS00000003 = "XS00000003";
public static final String XS00000004 = "XS00000004";
public static final String XE00000001 = "XE00000001";
public static final String XE00000002 = "XE00000002";
public static final String XE00000003 = "XE00000003";
public static final String XE00000004 = "XE00000004";
}
public static final class APPROLES {
public static final String SERVICE_NAME = "approles";
public static final String XE00000002 = "XE00000002";
public static final String XS00000002 = "XS00000002";
public static final String XE00000001 = "XE00000001";
public static final String XS00000001 = "XS00000001";
public static final String XE00000003 = "XE00000003";
public static final String XS00000003 = "XS00000003";
public static final String XE00000004 = "XE00000004";
public static final String XS00000004 = "XS00000004";
public static final String XS00000005 = "XS00000005";
public static final String XE00000005 = "XE00000005";
public static final String XE00000006 = "XE00000006";
public static final String XS00000006 = "XS00000006";
public static final String XE00000007 = "XE00000007";
public static final String XS00000007 = "XS00000007";
public static final String XS00000008 = "XS00000008";
public static final String XE00000008 = "XE00000008";
public static final String XE00000009 = "XE00000009";
public static final String XS00000009 = "XS00000009";
}
public static final class APIUSERS {
public static final String SERVICE_NAME = "apiusers";
public static final String XS00000003 = "XS00000003";
public static final String XE00000003 = "XE00000003";
public static final String XW00000001 = "XW00000001";
public static final String XW00000002 = "XW00000002";
public static final String XS00000001 = "XS00000001";
public static final String XE00000001 = "XE00000001";
}
public static final class PASSWORDPOLICY {
public static final String SERVICE_NAME = "passwordpolicy";
public static final String XW00000002 = "XW00000002";
public static final String XW00000001 = "XW00000001";
public static final String XW00000003 = "XW00000003";
public static final String XW00000004 = "XW00000004";
public static final String XW00000005 = "XW00000005";
public static final String XW00000006 = "XW00000006";
public static final String XW00000007 = "XW00000007";
public static final String XW00000008 = "XW00000008";
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
public final class ConstantsStatus {
public static final int ACTIVE = 1;
public static final int INACTIVE = 2;
public static final int ENABLED = 3;
public static final int DISABLED = 4;
public static final int LOCK = 5;
public static final int UNLOCK = 6;
public static final int INVALID = 7;
public static final int EXPIRED = 8;
public static final int DELETE = 9;
public static final int VALIDATED = 10;
public static final int START = 11;
public static final int STOP = 12;
public static final int APPROVED = 13;
public static final int QUITED = 14;
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
public final class ConstantsTimeInterval {
public static final Integer ONE_MINUTE = 60; // 1 minutes
public static final Integer ONE_HOUR = 60 * 60; // 1 hour
public static final Integer ONE_DAY = 60 * 60 * 24; // 1 day
public static final Integer ONE_WEEK = ONE_DAY * 7; // 1 week
public static final Integer TWO_WEEK = ONE_DAY * 14; // 2 week
public static final Integer ONE_MONTH = ONE_DAY * 30; // 1 month
public static final Integer TWO_MONTH = ONE_DAY * 60; // 2 month
/**
* The number of seconds in one year (= 60 * 60 * 24 * 365).
*/
public static final Integer ONE_YEAR = 60 * 60 * 24 * 365;
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.constants;
public class ContentType {
public static final String TEXT_PLAIN = "text/plain";
public static final String TEXT_PLAIN_UTF8 = "text/plain;charset=UTF-8";
public static final String TEXT_XML = "text/xml";
public static final String TEXT_XML_UTF8 = "text/xml;charset=UTF-8";
public static final String APPLICATION_JSON = "application/json";
public static final String APPLICATION_JSON_UTF8 = "application/json;charset=UTF-8";
public static final String APPLICATION_JWT = "application/jwt";
public static final String APPLICATION_JWT_UTF8 = "application/jwt;charset=UTF-8";
public static final String APPLICATION_XML = "application/xml";
public static final String APPLICATION_XML_UTF8 = "application/xml;charset=UTF-8";
public static final String IMAGE_GIF = "image/gif";
public static final String IMAGE_JPEG = "image/jpeg";
public static final String IMAGE_PNG = "image/png";
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto;
import org.apache.commons.codec.binary.Base32;
public class Base32Utils {
static Base32 base32 = new Base32();
public static String encode(String simple) {
return base32.encodeToString(simple.getBytes());
}
public static String encode(byte[] simple) {
return base32.encodeToString(simple);
}
public static byte[] decode(String cipher) {
return base32.decode(cipher);
}
}

View File

@@ -0,0 +1,147 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.commons.codec.binary.Base64;
/**
* Base64 Utils.
*
* @author Crystal.Sea
*
*/
public final class Base64Utils {
public static String encodeBase64(byte[] simple) {
String cipher = BytesUtils.bytes2String(Base64.encodeBase64(simple));
return cipher;
}
public static byte[] decoderBase64(String cipher) {
byte[] simple = Base64.decodeBase64(cipher);
return simple;
}
public static String encode(String simple) {
return encodeBase64(simple.getBytes());
}
public static String encoder(byte[] simple) {
return encodeBase64(simple);
}
public static String decode(String cipher) {
return BytesUtils.bytes2String(decoderBase64(cipher));
}
public static byte[] decoder(String cipher) {
return decoderBase64(cipher);
}
/**
* encode file to base64 Code String.
*
* @param fileName file path
* @return *
* @throws Exception e
*/
public static String fileToBase64(String fileName) throws Exception {
File file = new File(fileName);
FileInputStream inputFile = new FileInputStream(file);
byte[] buffer = new byte[(int) file.length()];
inputFile.read(buffer);
inputFile.close();
return encodeBase64(buffer);
}
/**
* base64 Code decode String save to targetPath.
*
* @param base64Code String
* @param targetPath String
* @throws Exception e
*/
public static void decodeBase64ToFile(String base64Code, String targetPath) throws Exception {
byte[] buffer = decoderBase64(base64Code);
FileOutputStream out = new FileOutputStream(targetPath);
out.write(buffer);
out.close();
}
/**
* base64 code save to file.
*
* @param base64Code String
* @param targetPath String
* @throws Exception e
*/
public static void base64ToFile(String base64Code, String targetPath) throws Exception {
byte[] buffer = base64Code.getBytes();
FileOutputStream out = new FileOutputStream(targetPath);
out.write(buffer);
out.close();
}
/**
* base64UrlEncode.
* @param simple byte
* @return
*/
public static String base64UrlEncode(byte[] simple) {
// Regular base64
String s = new String(Base64.encodeBase64(simple));
// encoder
s = s.split("=")[0]; // Remove any trailing '='s
s = s.replace('+', '-'); // 62nd char of encoding
s = s.replace('/', '_'); // 63rd char of encoding
return s;
}
/**
* base64UrlDecode.
* @param cipher String
* @return
*/
public static byte[] base64UrlDecode(String cipher) {
String s = cipher;
s = s.replace('-', '+'); // 62nd char of encoding
s = s.replace('_', '/'); // 63rd char of encoding
switch (s.length() % 4) { // Pad with trailing '='s
case 0 :
break; // No pad chars in this case
case 2 :
s += "==";
break; // Two pad chars
case 3 :
s += "=";
break; // One pad char
default:
System.err.println("Illegal base64url String!");
}
return Base64.decodeBase64(s); // Standard base64 decoder
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto;
public final class BytesUtils {
public static String bytes2String(byte[] bytesArray) {
String result = "";
for (Byte bts : bytesArray) {
result += (char) bts.intValue();
}
return result;
}
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.crypto;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* @author Crystal.Sea
* * algorithm Support MD5,SHA,SHA-1|SHA-256|SHA-384|SHA-512 then encodeBase64
*
*/
public final class DigestUtils {
public final class Algorithm {
public static final String MD5 = "MD5";
public static final String SHA = "SHA";
public static final String SHA1 = "SHA-1";
public static final String SHA256 = "SHA-256";
public static final String SHA384 = "SHA-384";
public static final String SHA512 = "SHA-512";
public static final String Base64 = "Base64";
}
/**
* @param simple
* @param algorithm MD5,SHA,SHA-1|SHA-256|SHA-384|SHA-512 then encodeBase64
* @return cipher
*/
public static String digestBase64(String simple,String algorithm) {
MessageDigest messageDigest;
String cipherBASE64="";
try {
messageDigest = MessageDigest.getInstance(algorithm.toUpperCase());
messageDigest.update(simple.getBytes());
byte[] bCipher=messageDigest.digest();
cipherBASE64=Base64Utils.encodeBase64(bCipher);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return cipherBASE64;
}
//B64
public static String md5B64(String simple) {
return digestBase64(simple,Algorithm.MD5);
}
public static String shaB64(String simple) {
return digestBase64(simple,Algorithm.SHA);
}
public static String sha1B64(String simple) {
return digestBase64(simple,Algorithm.SHA1);
}
public static String sha256B64(String simple) {
return digestBase64(simple,Algorithm.SHA256);
}
public static String sha384B64(String simple) {
return digestBase64(simple,Algorithm.SHA384);
}
public static String sha512B64(String simple) {
return digestBase64(simple,Algorithm.SHA512);
}
public static String digestHex(String simple,String algorithm) {
return digestHex( simple.getBytes(),algorithm);
}
/**
* @param simple
* @param algorithm MD5,SHA,SHA-1|SHA-256|SHA-384|SHA-512 then encodeHexString
* @return cipher
*/
public static String digestHex(byte[] simpleBytes,String algorithm) {
MessageDigest messageDigest;
String cipherHex="";
try {
messageDigest = MessageDigest.getInstance(algorithm.toUpperCase());
messageDigest.update(simpleBytes);
byte[] bCipher=messageDigest.digest();
cipherHex=HexUtils.bytes2HexString(bCipher);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return cipherHex;
}
//HEX
public static String md5Hex(String simple) {
return digestHex(simple,Algorithm.MD5);
}
public static String shaHex(String simple) {
return digestHex(simple,Algorithm.SHA);
}
public static String sha1Hex(String simple) {
return digestHex(simple,Algorithm.SHA1);
}
public static String sha256Hex(String simple) {
return digestHex(simple,Algorithm.SHA256);
}
public static String sha384Hex(String simple) {
return digestHex(simple,Algorithm.SHA384);
}
public static String sha512Hex(String simple) {
return digestHex(simple,Algorithm.SHA512);
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.crypto;
import java.io.UnsupportedEncodingException;
/**
* @author Crystal.Sea
*
*/
public final class HexUtils {
static final byte[] HEX_CHAR_TABLE = {
(byte) '0', (byte) '1', (byte) '2',(byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
(byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c',(byte) 'd', (byte) 'e', (byte) 'f'
};
public static String hex2String(byte[] b) {
String result = "";
for (int i = 0; i < b.length; i++) {
result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
}
return result;
}
public static String bytes2HexString(byte[] raw) {
byte[] hex = new byte[2 * raw.length];
int index = 0;
for (byte b : raw) {
int v = b & 0xFF;
hex[index++] = HEX_CHAR_TABLE[v >>> 4];
hex[index++] = HEX_CHAR_TABLE[v & 0xF];
}
String s = "";
try {
s = new String(hex, "ASCII");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return s;
}
public static byte[] hex2Bytes(char[] hex) {
int length = hex.length / 2;
byte[] raw = new byte[length];
for (int i = 0; i < length; i++) {
int high = Character.digit(hex[i * 2], 16);
int low = Character.digit(hex[i * 2 + 1], 16);
int value = (high << 4) | low;
if (value > 127)
value -= 256;
raw[i] = (byte) value;
}
return raw;
}
public static byte[] hex2Bytes(String hex) {
return hex2Bytes(hex.toCharArray());
}
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto;
public class KeyPairSize {
public static final int KEY_SIZE_1024 = 1024;
public static final int KEY_SIZE_2048 = 2048;
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* KeyPairType.java
*/
package org.maxkey.crypto;
/**
* Key pair type. Enum constant names are compatible with JCA standard names.
*
* @see <a
* href="http://download.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html">JCA
* Standard Names</a>
*/
public enum KeyPairType {
/** RSA key pair type. */
RSA,
/** DSA key pair type. */
DSA,
/** ECDSA key pair type. */
ECDSA;
}

View File

@@ -0,0 +1,246 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* KeyPairUtil.java
*/
package org.maxkey.crypto;
import java.security.InvalidParameterException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.DSAKey;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.ECKey;
import java.security.interfaces.RSAKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.interfaces.DHKey;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.DHKeyParameters;
import org.bouncycastle.crypto.params.DSAKeyParameters;
import org.bouncycastle.crypto.params.ECKeyParameters;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.maxkey.crypto.cert.CryptoException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Provides utility methods for the generation of keys.
*/
public final class KeyPairUtil
{
/** Logger */
private static final Logger _logger = LoggerFactory.getLogger(KeyPairUtil.class);
/** Constant representing unknown key size */
public static final int UNKNOWN_KEY_SIZE = -1;
public static final int DEFAULT_KEY_SIZE = 1024;
public static final String PUBLIC_KEY = "publicKey";
public static final String PRIVATE_KEY = "privateKey";
/**
* Private to prevent construction.
*/
private KeyPairUtil()
{
// Nothing to do
}
public static KeyPair genKeyPair(KeyPairType keyPairType) throws CryptoException, NoSuchProviderException{
return genKeyPair( keyPairType, DEFAULT_KEY_SIZE);
}
/**
* Generate a key pair.
*
* @param keyPairType Key pair type to generate
* @param iKeySize Key size of key pair
* @return A key pair
* @throws CryptoException If there was a problem generating the key pair
* @throws NoSuchProviderException
*/
public static KeyPair genKeyPair(KeyPairType keyPairType, int keySize)throws CryptoException, NoSuchProviderException
{
try{
return genKeyPair(keyPairType,null,keySize);
}catch (InvalidParameterException ex){
ex.printStackTrace();
throw new CryptoException("Invalid parameter for a ''"+keyPairType+"'' key pair." , ex);
}
}
public static KeyPair genKeyPair(KeyPairType keyPairType,String provider)throws CryptoException, NoSuchProviderException{
return genKeyPair(keyPairType,provider,DEFAULT_KEY_SIZE);
}
/**
* Generate a key pair.
*
* @param keyPairType Key pair type to generate
* @param iKeySize Key size of key pair
* @return A key pair
* @throws CryptoException If there was a problem generating the key pair
* @throws NoSuchProviderException
*/
public static KeyPair genKeyPair(KeyPairType keyPairType,String provider, int keySize)throws CryptoException, NoSuchProviderException
{
try{
if(keyPairType==KeyPairType.ECDSA){
throw new CryptoException("Could not support ''"+keyPairType+"'' key pair.");
}
KeyPairGenerator keyPairGenerator =null;
if(provider==null){
keyPairGenerator = KeyPairGenerator.getInstance(keyPairType.name());
}else{
keyPairGenerator = KeyPairGenerator.getInstance(keyPairType.name(),provider);
}
// Create a SecureRandom
SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
//SecureRandom rand = new SecureRandom();
// Initialize key pair generator with key strength and a randomness
keyPairGenerator.initialize(keySize, rand);
// Generate and return the key pair
return keyPairGenerator.generateKeyPair();
}catch (NoSuchAlgorithmException ex){
ex.printStackTrace();
throw new CryptoException("Could not generate ''"+keyPairType+"'' key pair.", ex);
}catch (InvalidParameterException ex){
ex.printStackTrace();
throw new CryptoException("Invalid parameter for a ''"+keyPairType+"'' key pair." , ex);
}
}
public static Map<String, Object> genKeyPairMap(KeyPairType keyPairType) throws Exception {
return genKeyPairMap(keyPairType,DEFAULT_KEY_SIZE);
}
public static Map<String, Object> genKeyPairMap(KeyPairType keyPairType, int keySize) throws Exception {
Map<String, Object> keyMap = new HashMap<String, Object>(2);
if(keyPairType==KeyPairType.RSA){
KeyPair keyPair=genKeyPair(keyPairType,keySize);
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
keyMap.put(PUBLIC_KEY , publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
}else if(keyPairType==KeyPairType.DSA){
KeyPair keyPair=genKeyPair(keyPairType,keySize);
DSAPublicKey publicKey = (DSAPublicKey) keyPair.getPublic();
DSAPrivateKey privateKey = (DSAPrivateKey) keyPair.getPrivate();
keyMap.put(PUBLIC_KEY , publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
}
return keyMap;
}
public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return Base64Utils.encoder(key.getEncoded());
}
public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return Base64Utils.encoder(key.getEncoded());
}
/**
* Get the key size of a public key.
*
* @param pubKey The public key
* @return The key size, {@link #UNKNOWN_KEY_SIZE} if not known
*/
public static int getKeyLength(PublicKey pubKey)
{
if (pubKey instanceof RSAKey)
{
return ((RSAKey) pubKey).getModulus().bitLength();
}
else if (pubKey instanceof DSAKey)
{
return ((DSAKey) pubKey).getParams().getP().bitLength();
}
else if (pubKey instanceof DHKey)
{
return ((DHKey) pubKey).getParams().getP().bitLength();
}
else if (pubKey instanceof ECKey)
{
// TODO: how to get key size from these?
return UNKNOWN_KEY_SIZE;
}
_logger.warn("Don't know how to get key size from key " + pubKey);
return UNKNOWN_KEY_SIZE;
}
/**
* Get the key size of a key represented by key parameters.
*
* @param keyParams The key parameters
* @return The key size, {@link #UNKNOWN_KEY_SIZE} if not known
*/
public static int getKeyLength(AsymmetricKeyParameter keyParams)
{
if (keyParams instanceof RSAKeyParameters)
{
return ((RSAKeyParameters) keyParams).getModulus().bitLength();
}
else if (keyParams instanceof DSAKeyParameters)
{
return ((DSAKeyParameters) keyParams).getParameters().getP().bitLength();
}
else if (keyParams instanceof DHKeyParameters)
{
return ((DHKeyParameters) keyParams).getParameters().getP().bitLength();
}
else if (keyParams instanceof ECKeyParameters)
{
// TODO: how to get key length from these?
return UNKNOWN_KEY_SIZE;
}
_logger.warn("Don't know how to get key size from parameters " + keyParams);
return UNKNOWN_KEY_SIZE;
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.crypto;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
/**
* 类似linux或Unix上md5sum是用来计算和校验文件报文摘要的工具程序
* @author Crystal.Sea
*
*/
public class Md5Sum {
/**
*
*/
public Md5Sum() {
}
public static String produce(File file) throws FileNotFoundException {
String md5value = null;
FileInputStream in = new FileInputStream(file);
try {
MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(byteBuffer);
byte[] bCipher=messageDigest.digest();
md5value=HexUtils.bytes2HexString(bCipher);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
md5value+=" *"+file.getName();
return md5value;
}
public static boolean check(File file,String md5String) throws FileNotFoundException{
String md5value = produce( file);
return md5value.equals(md5String)?true:false;
}
}

View File

@@ -0,0 +1,177 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
public final class RSAUtils {
public static final String KEY_ALGORTHM = "RSA";
public static final String PUBLIC_KEY = "RSAPublicKey";
public static final String PRIVATE_KEY = "RSAPrivateKey";
public static Map<String, Object> genKeyPair() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM);
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<String, Object>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
public static byte[] getPublicKey(Map<String, Object> keyMap)throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return key.getEncoded();
}
public static byte[] getPrivateKey(Map<String, Object> keyMap)throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return key.getEncoded();
}
public static String getPublicKey2Hex(Map<String, Object> keyMap)throws Exception {
return HexUtils.bytes2HexString(getPublicKey(keyMap));
}
public static String getPrivateKey2Hex(Map<String, Object> keyMap)throws Exception {
return HexUtils.bytes2HexString(getPrivateKey(keyMap));
}
/**
* <20><>˽Կ<CBBD><D4BF><EFBFBD><EFBFBD>
* @param data <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param hexKey <20><>Կ
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, String hexKey)throws Exception {
byte[] keyBytes = HexUtils.hex2Bytes(hexKey);
return encryptByPrivateKey(data,keyBytes);
}
public static byte[] encryptByPrivateKey(byte[] data, byte[] keyBytes)throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
// <20><><EFBFBD><EFBFBD>ݼ<EFBFBD><DDBC><EFBFBD>
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* <20><>˽Կ<CBBD><D4BF><EFBFBD><EFBFBD>
* @param data <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param hexKey <20><>Կ
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] data, String hexKey)throws Exception {
// <20><>˽Կ<CBBD><D4BF><EFBFBD><EFBFBD>
byte[] keyBytes = HexUtils.hex2Bytes(hexKey);
return decryptByPrivateKey(data,keyBytes);
}
public static byte[] decryptByPrivateKey(byte[] data, byte[] keyBytes)throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
// <20><><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD>
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* <20>ù<EFBFBD>Կ<EFBFBD><D4BF><EFBFBD><EFBFBD>
* @param data <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param hexKey <20><>Կ
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, String hexKey)throws Exception {
// <20>Թ<EFBFBD>Կ<EFBFBD><D4BF><EFBFBD><EFBFBD>
byte[] keyBytes = HexUtils.hex2Bytes(hexKey);
return encryptByPublicKey(data,keyBytes);
}
public static byte[] encryptByPublicKey(byte[] data, byte[] keyBytes)throws Exception {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
// <20><><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD>
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* <20>ù<EFBFBD>Կ<EFBFBD><D4BF><EFBFBD><EFBFBD>
* @param data <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param hexKey <20><>Կ
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] data, String hexKey)throws Exception {
// <20><>˽Կ<CBBD><D4BF><EFBFBD><EFBFBD>
byte[] keyBytes = HexUtils.hex2Bytes(hexKey);
return decryptByPublicKey(data,keyBytes);
}
public static byte[] decryptByPublicKey(byte[] data, byte[] keyBytes)throws Exception {
// <20><>˽Կ<CBBD><D4BF><EFBFBD><EFBFBD>
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
// <20><><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD>
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
}

View File

@@ -0,0 +1,285 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.crypto;
import java.io.UnsupportedEncodingException;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.logging.LogFactory;
import org.maxkey.util.StringGenerator;
/**
* Reciprocal cipher or Symmetric-key algorithm
*
* algorithm Support DES,DESede,Blowfish and AES
*
* default key value use ReciprocalUtils.defaultKey
*
* generateKey is generate random key for algorithm
*
* @author Crystal.Sea
*
*/
public final class ReciprocalUtils {
private static final String defaultKey = "l0JqT7NvIzP9oRaG4kFc1QmD_bWu3x8E5yS2h6"; //
public final class Algorithm {
public static final String DES = "DES";
public static final String DESede = "DESede";
public static final String Blowfish = "Blowfish";
public static final String AES = "AES";
}
public static byte[] encode(byte[] simpleBytes, SecretKey secretKey, String algorithm) {
// Create the ciphers
Cipher ecipher;
byte[] byteFinal = null;
try {
ecipher = Cipher.getInstance(secretKey.getAlgorithm());
// Encode the string into bytes using utf-8
ecipher.init(Cipher.ENCRYPT_MODE, secretKey);
// Encrypt
byteFinal = ecipher.doFinal(simpleBytes);
return byteFinal;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @param simple
* @param secretKey must length
* @return
* @throws Exception
*/
public static byte[] encode(String simple, String secretKey, String algorithm) {
if (keyLengthCheck(secretKey, algorithm)) {
SecretKey key = generatorKey(secretKey, algorithm);
try {
return encode(simple.getBytes("UTF-8"), key, algorithm);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return null;
}
public static byte[] decoder(byte[] ciphersBytes, SecretKey secretKey, String algorithm) {
Cipher cipher;
byte[] byteFinal = null;
try {
cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byteFinal = cipher.doFinal(ciphersBytes);
// String simple=new String(byteFinal, "UTF8" );
// return simple;
return byteFinal;
} catch (Exception e) {
e.printStackTrace();
} finally {
cipher = null;
}
return null;
}
public static String decoder(byte[] ciphersBytes, String secretKey, String algorithm) {
if (keyLengthCheck(secretKey, algorithm)) {
SecretKey key = generatorKey(secretKey, algorithm);
try {
return new String(decoder(ciphersBytes, key, algorithm), "UTF8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return null;
}
public static byte[] encodeByDefaultKey(String simple, String algorithm) {
SecretKey key = generatorDefaultKey(algorithm);
return encode(simple.getBytes(), key, algorithm);
}
public static String encode2HexByDefaultKey(String simple, String algorithm) {
byte[] byteFinal = encodeByDefaultKey(simple, algorithm);
String cipherHex = HexUtils.bytes2HexString(byteFinal);
return cipherHex;
}
public static byte[] decoderByDefaultKey(byte[] byteCiphers, String algorithm) {
SecretKey key = generatorDefaultKey(algorithm);
return decoder(byteCiphers, key, algorithm);
}
public static String decoderHexByDefaultKey(String ciphers, String algorithm) {
byte[] byteSimple = HexUtils.hex2Bytes(ciphers);
byte[] byteFinal = decoderByDefaultKey(byteSimple, algorithm);
String simple = null;
try {
simple = new String(byteFinal, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return simple;
}
public static SecretKey generatorDefaultKey(String algorithm) {
try {
Security.addProvider(new com.sun.crypto.provider.SunJCE());
String secretKey = defaultKey;
if (algorithm.equals(Algorithm.DES)) {
secretKey = defaultKey.substring(0, 8);
} else if (algorithm.equals(Algorithm.AES) || algorithm.equals(Algorithm.Blowfish)) {
secretKey = defaultKey.substring(0, 16);
} else if (algorithm.equals(Algorithm.DESede)) {
secretKey = defaultKey.substring(0, 24);
}
// System.out.println("defaultKey : "+secretKey);
SecretKey key = new SecretKeySpec(secretKey.getBytes(), algorithm);
return key;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static SecretKey generatorKey(String secretKey, String algorithm) {
try {
SecretKey key = new SecretKeySpec(secretKey.getBytes(), algorithm);
return key;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String encode2Hex(String simple, String secretKey, String algorithm) {
if (keyLengthCheck(secretKey, algorithm)) {
byte[] cipher = encode(simple, secretKey, algorithm);
// Encode bytes to HEX to get a string
return HexUtils.bytes2HexString(cipher);
}
return null;
}
public static String decoderHex(String ciphers, String secretKey, String algorithm) {
if (keyLengthCheck(secretKey, algorithm)) {
byte[] byteSimple = HexUtils.hex2Bytes(ciphers);
return decoder(byteSimple, secretKey, algorithm);
}
return null;
}
private static boolean keyLengthCheck(String secretKey, String algorithm) {
boolean lengthCheck = false;
if (algorithm.equals(Algorithm.DES)) {
if (secretKey.length() == 8) {
lengthCheck = true;
} else {
LogFactory.getLog(ReciprocalUtils.class)
.debug("key length is " + secretKey.getBytes().length + " ,must lequal 8");
}
} else if (algorithm.equals(Algorithm.DESede)) {
if (secretKey.length() == 24) {
lengthCheck = true;
} else {
LogFactory.getLog(ReciprocalUtils.class)
.debug("key length is " + secretKey.getBytes().length + " ,must equal 24");
}
} else if (algorithm.equals(Algorithm.AES)) {
if (secretKey.length() == 16) {
lengthCheck = true;
} else {
LogFactory.getLog(ReciprocalUtils.class)
.debug("key length is " + secretKey.getBytes().length + " ,must equal 16");
}
} else if (algorithm.equals(Algorithm.Blowfish)) {
if (secretKey.length() <= 16) {
lengthCheck = true;
} else {
LogFactory.getLog(ReciprocalUtils.class)
.debug("key length is " + secretKey.getBytes().length + " ,must be less then 16");
}
}
return lengthCheck;
}
/**
* @param simple
* @param secretKey must length is 16
* @return
*/
public static String aesEncode(String simple, String secretKey) {
return encode2Hex(simple, secretKey, Algorithm.AES);
}
public static String aesDecoder(String ciphers, String secretKey) {
return decoderHex(ciphers, secretKey, Algorithm.AES);
}
/**
* encode by defaultKey with Algorithm.AES
*
* @param simple
* @return Hex
*/
public static String encode(String simple) {
return encode2HexByDefaultKey(simple, Algorithm.AES);
}
/**
* decoder by defaultKey with Algorithm.AES
*
* @param ciphers is HEX
*
* @return
*/
public static String decoder(String ciphers) {
return decoderHexByDefaultKey(ciphers, Algorithm.AES);
}
public static String generateKey(String algorithm) {
if (algorithm.equals(Algorithm.DES)) {
return (new StringGenerator(8)).randomGenerate();
} else if (algorithm.equals(Algorithm.AES)) {
return (new StringGenerator(16)).randomGenerate();
} else if (algorithm.equals(Algorithm.Blowfish)) {
return (new StringGenerator(16)).randomGenerate();
} else if (algorithm.equals(Algorithm.DESede)) {
return (new StringGenerator(24)).randomGenerate();
} else {
return (new StringGenerator()).uniqueGenerate();
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto;
import java.util.Arrays;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
/**
* SM3.
* @author Crystal.Sea
*
*/
public class SM3 {
/**
* 计算SM3摘要值
*
* @param simple 原文
* @return 摘要值对于SM3算法来说是32字节
*/
public static byte[] encode(byte[] simple) {
SM3Digest digest = new SM3Digest();
digest.update(simple, 0, simple.length);
byte[] hash = new byte[digest.getDigestSize()];
digest.doFinal(hash, 0);
return hash;
}
/**
* 验证摘要
*
* @param simple 原文
* @param cipher 摘要值
* @return 返回true标识验证成功false标识验证失败
*/
public static boolean verify(byte[] simple, byte[] cipher) {
byte[] newHash = encode(simple);
if (Arrays.equals(newHash, cipher)) {
return true;
} else {
return false;
}
}
/**
* 计算SM3 Mac值
*
* @param key key值可以是任意长度的字节数组
* @param srcData 原文
* @return Mac值对于HMac-SM3来说是32字节
*/
public static byte[] hmac(byte[] key, byte[] simple) {
KeyParameter keyParameter = new KeyParameter(key);
SM3Digest digest = new SM3Digest();
HMac mac = new HMac(digest);
mac.init(keyParameter);
mac.update(simple, 0, simple.length);
byte[] result = new byte[mac.getMacSize()];
mac.doFinal(result, 0);
return result;
}
}

View File

@@ -0,0 +1,426 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.cert;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import javax.crypto.Cipher;
import org.maxkey.crypto.Base64Utils;
import org.maxkey.crypto.keystore.KeyStoreUtil;
/** *//**
* <p>
* 证书加密解密工具<E5B7A5>?
* </p>
* @version 1.0
*/
public class CertCrypto {
/** *//**
* Java密钥<E5AF86>?Java 密钥库JKS)KEY_STORE
*/
public static final String KEY_STORE = "JKS";
public static final String X509 = "X.509";
/** *//**
* 文件读取缓冲区大<E58CBA>?
*/
private static final int CACHE_SIZE = 2048;
/** *//**
* <20>?<3F><>文件加密<E58AA0>?
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/** *//**
* <20>?<3F><>文件解密<E8A7A3>?
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/** *//**
* <p>
* 私钥加密
* </p>
*
* @param data 源数<E6BA90>?
* @param keyStorePath 密钥库存储路<E582A8>?
* @param alias 密钥库别<E5BA93>?
* @param password 密钥库密<E5BA93>?
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, KeyStore keyStore, String alias, String password)
throws Exception {
// 取得私钥
PrivateKey privateKey = KeyStoreUtil.getPrivateKey(keyStore, alias, password);
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加<E6AEB5>?
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/** *//**
* <p>
* 文件私钥加密
* </p>
* <p>
* 过大的文件可能会导致内存溢出
* </>
*
* @param filePath 文件路径
* @param keyStorePath 密钥库存储路<E582A8>?
* @param alias 密钥库别<E5BA93>?
* @param password 密钥库密<E5BA93>?
* @return
* @throws Exception
*/
public static byte[] encryptFileByPrivateKey(String filePath, KeyStore keyStore, String alias, String password)
throws Exception {
byte[] data = fileToByte(filePath);
return encryptByPrivateKey(data, keyStore, alias, password);
}
/** *//**
* <p>
* 文件加密
* </p>
*
* @param srcFilePath 源文<E6BA90>?
* @param destFilePath 加密后文<E5908E>?
* @param keyStorePath 密钥库存储路<E582A8>?
* @param alias 密钥库别<E5BA93>?
* @param password 密钥库密<E5BA93>?
* @throws Exception
*/
public static void encryptFileByPrivateKey(String srcFilePath, String destFilePath,KeyStore keyStore, String alias, String password)
throws Exception {
// 取得私钥
PrivateKey privateKey = KeyStoreUtil.getPrivateKey(keyStore, alias, password);
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
File srcFile = new File(srcFilePath);
FileInputStream in = new FileInputStream(srcFile);
File destFile = new File(destFilePath);
if (!destFile.getParentFile().exists()) {
destFile.getParentFile().mkdirs();
}
destFile.createNewFile();
OutputStream out = new FileOutputStream(destFile);
byte[] data = new byte[MAX_ENCRYPT_BLOCK];
byte[] encryptedData; // 加密<E58AA0>?
while (in.read(data) != -1) {
encryptedData = cipher.doFinal(data);
out.write(encryptedData, 0, encryptedData.length);
out.flush();
}
out.close();
in.close();
}
/** *//**
* <p>
* 文件加密成BASE64编码的字符串
* </p>
*
* @param filePath 文件路径
* @param keyStorePath 密钥库存储路<E582A8>?
* @param alias 密钥库别<E5BA93>?
* @param password 密钥库密<E5BA93>?
* @return
* @throws Exception
*/
public static String encryptFileToBase64ByPrivateKey(String filePath,KeyStore keyStore, String alias, String password)
throws Exception {
byte[] encryptedData = encryptFileByPrivateKey(filePath, keyStore, alias, password);
return Base64Utils.encoder(encryptedData);
}
/** *//**
* <p>
* 私钥解密
* </p>
*
* @param encryptedData 已加密数<E5AF86>?
* @param keyStorePath 密钥库存储路<E582A8>?
* @param alias 密钥库别<E5BA93>?
* @param password 密钥库密<E5BA93>?
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] encryptedData, KeyStore keyStore, String alias, String password)
throws Exception {
// 取得私钥
PrivateKey privateKey = KeyStoreUtil.getPrivateKey(keyStore, alias, password);
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
// 解密byte数组<E695B0>?<3F><>长度限制: 128
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解<E6AEB5>?
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/** *//**
* <p>
* 公钥加密
* </p>
*
* @param data 源数<E6BA90>?
* @param certificatePath 证书存储路径
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data, Certificate certificate)
throws Exception {
// 取得公钥
PublicKey publicKey = KeyStoreUtil.getPublicKey(certificate);
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加<E6AEB5>?
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/** *//**
* <p>
* 公钥解密
* </p>
*
* @param encryptedData 已加密数<E5AF86>?
* @param certificatePath 证书存储路径
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] encryptedData, Certificate certificate)
throws Exception {
PublicKey publicKey = KeyStoreUtil.getPublicKey(certificate);
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解<E6AEB5>?
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/** *//**
* <p>
* 文件解密
* </p>
*
* @param srcFilePath 源文<E6BA90>?
* @param destFilePath 目标文件
* @param certificatePath 证书存储路径
* @throws Exception
*/
public static void decryptFileByPublicKey(String srcFilePath, String destFilePath,Certificate certificate)
throws Exception {
PublicKey publicKey = KeyStoreUtil.getPublicKey(certificate);
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
File srcFile = new File(srcFilePath);
FileInputStream in = new FileInputStream(srcFile);
File destFile = new File(destFilePath);
if (!destFile.getParentFile().exists()) {
destFile.getParentFile().mkdirs();
}
destFile.createNewFile();
OutputStream out = new FileOutputStream(destFile);
byte[] data = new byte[MAX_DECRYPT_BLOCK];
byte[] decryptedData; // 解密<E8A7A3>?
while (in.read(data) != -1) {
decryptedData = cipher.doFinal(data);
out.write(decryptedData, 0, decryptedData.length);
out.flush();
}
out.close();
in.close();
}
/** *//**
* <p>
* 文件转换为byte数组
* </p>
*
* @param filePath 文件路径
* @return
* @throws Exception
*/
public static byte[] fileToByte(String filePath) throws Exception {
byte[] data = new byte[0];
File file = new File(filePath);
if (file.exists()) {
FileInputStream in = new FileInputStream(file);
ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
byte[] cache = new byte[CACHE_SIZE];
int nRead = 0;
while ((nRead = in.read(cache)) != -1) {
out.write(cache, 0, nRead);
out.flush();
}
out.close();
in.close();
data = out.toByteArray();
}
return data;
}
/** *//**
* <p>
* 二进制数据写文件
* </p>
*
* @param bytes 二进制数<E588B6>?
* @param filePath 文件生成目录
*/
public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
InputStream in = new ByteArrayInputStream(bytes);
File destFile = new File(filePath);
if (!destFile.getParentFile().exists()) {
destFile.getParentFile().mkdirs();
}
destFile.createNewFile();
OutputStream out = new FileOutputStream(destFile);
byte[] cache = new byte[CACHE_SIZE];
int nRead = 0;
while ((nRead = in.read(cache)) != -1) {
out.write(cache, 0, nRead);
out.flush();
}
out.close();
in.close();
}
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
long length = file.length();
if (length > Integer.MAX_VALUE) {
// File is too large
}
byte[] bytes = new byte[(int)length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
is.close();
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
return bytes;
}
public static void main(String[] args) throws Exception {
// String result = encryptFileToBase64ByPrivateKey("C:\\sp.cer", "C:\\sp-keystore.jks", "sp", "secret");
// System.out.println(result);
//Certificate certificate = getCertificate("C:\\sp-keystore.jks", "sp", "secret");
// System.out.println("certificate 1:"+certificate);
//File file = new File("C:\\para-keystore.jks");
//byte[] content = getBytesFromFile(file);
// System.out.println("base64keystore:\n"+Base64.encodeBase64String(content));
KeyStore ks = KeyStore.getInstance("JKS");
String b64EncodedKeystore = "/u3+7QAAAAIAAAACAAAAAQACc3AAAAErlmk7hAAAArowggK2MA4GCisGAQQBKgIRAQEFAASCAqIw4jynaKwOlOP74OM2+0lnYX8MOhvk0r71kvcbv9cusyIua3FJaIg1NBmgDrvF2JcUNcAhnyuBrafzW+3INGs8NNnmsPNgSPQ5cIMKRZ+44xxEmafy+FYPgw5RlmL+gXB/buiK1FzVuukjCR7/GCbQB2T0I1bZn5Ok/U0AlfGnAGBcXOR3efjdtKKImPBtMHQ9kBoCIlgROVKPEcSxPi7fm2SlN+tVjv1y9toYw2wRP+zsW5CAfY2mnRkQg58BtE2LhYhedSUUuaJAWTlWaWqA9rbTZmXlYqqOB/t86aYNuadT8nAu468MIucL3F2RQdMt9xDD3qRidT+h1I7ShnaF7pkUvynE5QKW3EIPhTaiRvMSUf6a984G4WerpdgmbzYEHUC9Kfw6WHcgKcGB5oAg4R2nlyEGLd2SBFv2vMRnXucwuofECK15YqCbu6wZGhQDKiGZo8MNcu8mPCq7vujOl4Azkjx1YyU1VHTQTyHP9BoOqS4lA8SjdEEGOm6p3R+CrwRratgET0UlopMInxuIvnuxXp5Vq4fHuY0GI65MRVQt9mSp5zeYvAYPYLSPmhcE2KchIR1Cb7NPbPID8D/EkNuCxG9FNPBhhtgMRdbOejJ3NPpt43DDt3nTpn/5pgBLsBxQ7hlPOb3Y4hsKCEI4UyVl+fTQieNIyEaAnt2Q/NNVGDJlc4aIAdDEfbOVbVdyYDViHskwTiKDdin4mAqTGj+qr0MVpoye6daZduftG85yx/1AnEjvPqUhKvi1kMKBi6q3z6XUMIq09RaQepx6xMboaiiqCU+Bi9kvdh3XNbnQ64DNPOhzytLAiBApb2IRaY1fkKSYOz+hFj0HbxF1cn5ITaQT1KeestiS+PuBO8JUR1yxTU0JQ4Tea0quTB+ragAAAAEABVguNTA5AAACSjCCAkYwggGvAgRMscTWMA0GCSqGSIb3DQEBBQUAMGoxJDAiBgkqhkiG9w0BCQEWFWphbWVzLnMuY294QGdtYWlsLmNvbTELMAkGA1UEBhMCVVMxGTAXBgNVBAoMEFNlcnZpY2UgUHJvdmlkZXIxCzAJBgNVBAsMAnNwMQ0wCwYDVQQDDARqY294MB4XDTEwMTAxMDEzNTExOFoXDTIwMTAwNzEzNTExOFowajEkMCIGCSqGSIb3DQEJARYVamFtZXMucy5jb3hAZ21haWwuY29tMQswCQYDVQQGEwJVUzEZMBcGA1UECgwQU2VydmljZSBQcm92aWRlcjELMAkGA1UECwwCc3AxDTALBgNVBAMMBGpjb3gwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIvtAFv5pWA6oRlLz/JhEG1Y7+6Wcvc2aU4rAH4PdWlmr5YkpA/gEd/J25AilVIE+c8nQwIzn5rDgJFGoBfjN/jUkKWLcB5jZC8SFzEx5zvGnR9wWgnbBL+jWQTal8M10ilhbRfklYLpkyTrwYWQdpDmMqVrN9wbNgU2imTihooNAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAdwn3tIk3612PRNtkxcuW/O5MKQyoy6KTS7V95KklJX452zebWDeM6/dR+XWVJLhRfN8+87cyos5HMYjIFVUJFNl9W5+UnRK75ku2hHBvPuU3ZTuW3/vGrNOLuaroPqELp+bNbfZkr2hezpeQl/4JKRFE418dvJJXW2OxE4A1K0sAAAACAANpZHAAAAErlm6iEQAFWC41MDkAAAJOMIICSjCCAbMCBEyxxXgwDQYJKoZIhvcNAQEFBQAwbDEkMCIGCSqGSIb3DQEJARYVamFtZXMucy5jb3hAZ21haWwuY29tMQswCQYDVQQGEwJVUzEaMBgGA1UECgwRSWRlbnRpdHkgUHJvdmlkZXIxDDAKBgNVBAsMA2lkcDENMAsGA1UEAwwEamNveDAeFw0xMDEwMTAxMzU0MDBaFw0yMDEwMDcxMzU0MDBaMGwxJDAiBgkqhkiG9w0BCQEWFWphbWVzLnMuY294QGdtYWlsLmNvbTELMAkGA1UEBhMCVVMxGjAYBgNVBAoMEUlkZW50aXR5IFByb3ZpZGVyMQwwCgYDVQQLDANpZHAxDTALBgNVBAMMBGpjb3gwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIt33orAL6MajhA8jeXaf8aPbIX24dlv0HwBBmdLBzkrO0I3bELtKSzbKFBkIwQZKaFHYdT7cxmy1epwffYsX2Ipguz99wGgH92GiWCLuPr14HqMAz/wx/1pAFFERa5rxadq0Jxmk1SF8gdz7FtoQOT0WUnIcs20yXta0Abqd1AxAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAOCsgCB7zc/OrY8u54nUb2apJEZ20sSO48ilzn5PoGBQxFZJIg0E0eBTfCTNGQuF5anI4NZ7Q0gTRT8IBxeiPhksz+5NG4eCb6+4VyKJszx6rY7S6uq/08N3EMru5jyNVEn/o3F1QpwtlMDipH8s+dpuR6sEAcpugQYBH6F1MfI1iptlkKubwxS31ebaol0N4M5BFyA==";
String keystorePassword = "secret";
ks.load(new ByteArrayInputStream(Base64Utils.decoder(b64EncodedKeystore)), keystorePassword.toCharArray());
System.out.println("certificate 2:"+ks.getCertificate("sp"));
}
}

View File

@@ -0,0 +1,241 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.cert;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Date;
import org.maxkey.crypto.HexUtils;
import org.maxkey.crypto.keystore.KeyStoreUtil;
/** *//**
* <p>
* 证书数字签名
*
* @version 1.0
*/
public class CertSigner {
/** *//**
* <p>
* 生成数据签名
* </p>
*
* @param data 源数<E6BA90>?
* @param keyStorePath 密钥库存储路<E582A8>?
* @param alias x509Certificate alias
* @param password 密钥库密<E5BA93>?
* @return
* @throws Exception
*/
public static byte[] sign(byte[] data, KeyStore keyStore, String alias, String password) throws Exception {
// 获得证书
X509Certificate x509Certificate = (X509Certificate) KeyStoreUtil.getCertificate(keyStore, alias, password);
// 取得私钥
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
// 构建签名
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
/** *//**
* <p>
* 验证签名
* </p>
*
* @param data 已加密数<E5AF86>?
* @param sign 数据签名[BASE64]
* @param certificatePath 证书存储路径
* @return
* @throws Exception
*/
public static boolean verifySign(byte[] data, String sign, X509Certificate certificate)
throws Exception {
// 获得公钥
PublicKey publicKey = certificate.getPublicKey();
// 构建签名
Signature signature = Signature.getInstance(certificate.getSigAlgName());
signature.initVerify(publicKey);
signature.update(data);
return signature.verify(HexUtils.hex2Bytes(sign));
}
/** *//**
* <p>
* 生成数据签名并以BASE64编码
* </p>
*
* @param data 源数<E6BA90>?
* @param keyStorePath 密钥库存储路<E582A8>?
* @param alias 密钥库别<E5BA93>?
* @param password 密钥库密<E5BA93>?
* @return
* @throws Exception
*/
public static String sign2Hex(byte[] data, KeyStore keyStore, String alias, String password)
throws Exception {
return HexUtils.bytes2HexString(sign(data, keyStore, alias, password));
}
/** *//**
* <p>
* BASE64解码->签名校验
* </p>
*
* @param base64String BASE64编码字符<E5AD97>?
* @param sign 数据签名[BASE64]
* @param certificatePath 证书存储路径
* @return
* @throws Exception
*/
public static boolean verifyHexSign(String HexString, String sign, X509Certificate certificate)
throws Exception {
byte[] data = HexUtils.hex2Bytes(HexString);
return verifySign(data, sign, certificate);
}
/** *//**
* <p>
* 生成文件数据签名(BASE64)
* </p>
* <p>
* <20>?<3F><>先将文件私钥加密再根据加密后的数据生成签名(BASE64)<>?用于小文<E5B08F>?
* </p>
*
* @param filePath 源文<E6BA90>?
* @param keyStorePath 密钥库存储路<E582A8>?
* @param alias 密钥库别<E5BA93>?
* @param password 密钥库密<E5BA93>?
* @return
* @throws Exception
*/
public static String signFile2HexWithEncrypt(String filePath, KeyStore keyStore, String alias, String password)
throws Exception {
byte[] encryptedData = CertCrypto.encryptFileByPrivateKey(filePath, keyStore, alias, password);
return sign2Hex(encryptedData, keyStore, alias, password);
}
/** *//**
* <p>
* BASE64解码->公钥解密-签名校验
* </p>
*
*
* @param base64String BASE64编码字符<E5AD97>?
* @param sign 数据签名[BASE64]
* @param certificatePath 证书存储路径
* @return
* @throws Exception
*/
public static boolean verifyHexSignWithDecrypt(String hexString, String sign, X509Certificate certificate)
throws Exception {
byte[] encryptedData = HexUtils.hex2Bytes(hexString);
byte[] data = CertCrypto.decryptByPublicKey(encryptedData, certificate);
return verifySign(data, sign, certificate);
}
/** *//**
* <p>
* 校验证书当前是否有效
* </p>
*
* @param certificate 证书
* @return
*/
public static boolean verifyCertificate(Certificate certificate) {
return verifyCertificate(new Date(), certificate);
}
/** *//**
* <p>
* 验证证书是否过期或无<E68896>?
* </p>
*
* @param date 日期
* @param certificate 证书
* @return
*/
public static boolean verifyCertificate(Date date, Certificate certificate) {
boolean isValid = true;
try {
X509Certificate x509Certificate = (X509Certificate) certificate;
x509Certificate.checkValidity(date);
} catch (Exception e) {
isValid = false;
}
return isValid;
}
/** *//**
* <p>
* 验证数字证书是在给定的日期是否有<E590A6>?
* </p>
*
* @param keyStorePath 密钥库存储路<E582A8>?
* @param alias 密钥库别<E5BA93>?
* @param password 密钥库密<E5BA93>?
* @return
*/
public static boolean verifyCertificate(Date date,KeyStore keyStore, String alias, String password) {
Certificate certificate;
try {
certificate = KeyStoreUtil.getCertificate(keyStore, alias, password);
return verifyCertificate(certificate);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/** *//**
* <p>
* 验证数字证书当前是否有效
* </p>
*
* @param keyStorePath 密钥库存储路<E582A8>?
* @param alias 密钥库别<E5BA93>?
* @param password 密钥库密<E5BA93>?
* @return
*/
public static boolean verifyCertificate(KeyStore keyStore, String alias, String password) {
return verifyCertificate(new Date(), keyStore, alias, password);
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* CryptoException.java
*/
package org.maxkey.crypto.cert;
/**
* Represents a cryptographic exception.
*/
public class CryptoException extends Exception {
/**
*
*/
private static final long serialVersionUID = -1879905141025077248L;
/**
* Creates a new CryptoException.
*/
public CryptoException() {
super();
}
/**
* Creates a new CryptoException with the specified message.
*
* @param sMessage
* Exception message
*/
public CryptoException(String sMessage) {
super(sMessage);
}
/**
* Creates a new CryptoException with the specified message and cause
* throwable.
*
* @param causeThrowable
* The throwable that caused this exception to be thrown
* @param sMessage
* Exception message
*/
public CryptoException(String sMessage, Throwable causeThrowable) {
super(sMessage, causeThrowable);
}
/**
* Creates a new CryptoException with the specified cause throwable.
*
* @param causeThrowable
* The throwable that caused this exception to be thrown
*/
public CryptoException(Throwable causeThrowable) {
super(causeThrowable);
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* NameUtil.java
*/
package org.maxkey.crypto.cert;
import java.util.Vector;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.x509.X509Name;
/**
* Provides utility methods relating to X50* names.
*/
public final class NameUtil {
/**
* Private to prevent construction.
*/
private NameUtil() {
// Nothing to do
}
/**
* Gets the common name from the given X509Name.
*
* @param name
* the X.509 name
* @return the common name, null if not found
*/
public static String getCommonName(X509Name name) {
if (name == null) {
return null;
}
Vector<?> values = name.getValues(X509Name.CN);
if (values == null || values.isEmpty()) {
return null;
}
return values.get(0).toString();
}
/**
* Gets the common name from the given X500Principal.
*
* @param name
* the X.500 principal
* @return the common name, null if not found
*/
public static String getCommonName(X500Principal name) {
if (name == null) {
return null;
}
return getCommonName(new X509Name(name.getName()));
}
}

View File

@@ -0,0 +1,206 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* NetUtil.java
*/
package org.maxkey.crypto.cert;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Networking utilities.
*
* @author Ville Skyttä
*/
public final class NetUtil
{
/** Logger */
private static final Logger _logger = LoggerFactory.getLogger(NetUtil.class);
// TODO: make this configurable
private static final int CONNECT_TIMEOUT = 10000;
// TODO: make this configurable
private static final int READ_TIMEOUT = 20000;
/**
* Private to prevent construction.
*/
private NetUtil()
{
// Nothing to do
}
/**
* Open an input stream to a GET(-like) operation on an URL.
*
* @param url The URL
* @return Input stream to the URL connection
* @throws IOException If an I/O error occurs
*/
public static InputStream openGetStream(URL url)
throws IOException
{
URLConnection conn = url.openConnection();
conn.setConnectTimeout(CONNECT_TIMEOUT);
conn.setReadTimeout(READ_TIMEOUT);
// TODO: User-Agent?
return conn.getInputStream();
}
/**
* Open an input stream to a POST(-like) operation on an URL.
*
* @param url The URL
* @param content Content to POST
* @param contentType Content type
* @return Input stream to the URL connection
* @throws IOException If an I/O error occurs
*/
public static InputStream openPostStream(URL url, byte[] content, String contentType)
throws IOException
{
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
conn.setConnectTimeout(CONNECT_TIMEOUT);
conn.setReadTimeout(READ_TIMEOUT);
// TODO: User-Agent?
if (contentType != null)
{
conn.setRequestProperty("Content-Type", contentType);
}
conn.setRequestProperty("Content-Length", String.valueOf(content.length));
OutputStream out = conn.getOutputStream();
try
{
out.write(content);
}
finally
{
out.close();
}
return conn.getInputStream();
}
/**
* Download the given URL to a temporary local file. The temporary file is marked for deletion at exit.
*
* @param url
* @return URL pointing to the temporary file, <code>url</code> itself if it's a file: one.
* @throws IOException
*/
public static URL download(URL url)
throws IOException
{
if ("file".equals(url.getProtocol()))
{
return url;
}
InputStream in = openGetStream(url);
File tempFile = null;
OutputStream out = null;
try
{
tempFile = File.createTempFile("portecle", null);
out = new BufferedOutputStream(new FileOutputStream(tempFile));
byte[] buf = new byte[2048];
int n;
while ((n = in.read(buf)) != -1)
{
out.write(buf, 0, n);
}
out.flush();
out.close();
}
catch (IOException e)
{
try
{
if (out != null)
{
out.close();
}
}
finally
{
if (tempFile != null && !tempFile.delete())
{
_logger.info("Could not delete temporary file " + tempFile);
}
}
throw e;
}
finally
{
in.close();
}
tempFile.deleteOnExit();
return tempFile.toURI().toURL();
}
/**
* Creates a URL pointing to a URL, URI or a File object.
*
* @param obj Object to create a URI to
* @return URL
* @throws ClassCastException if obj is not a supported object
* @throws MalformedURLException if converting obj to a URL fails
*/
public static URL toURL(Object obj)
throws MalformedURLException
{
if (obj instanceof File)
{
return ((File) obj).toURI().toURL();
}
else if (obj instanceof URI)
{
return ((URI) obj).toURL();
}
else
{
return (URL) obj;
}
}
}

View File

@@ -0,0 +1,189 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* SignatureType.java
*/
package org.maxkey.crypto.cert;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.maxkey.crypto.KeyPairType;
/**
* Signature type. Enum constant names are compatible with JCA standard names.
*
* @see <a href="http://download.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html">JCA
* Standard Names</a>
*/
public enum SignatureType
{
/** MD2 with RSA Signature Type */
MD2withRSA(PKCSObjectIdentifiers.md2WithRSAEncryption.getId()),
/** MD5 with RSA Signature Type */
MD5withRSA(PKCSObjectIdentifiers.md5WithRSAEncryption.getId()),
/** SHA-1 with RSA Signature Type */
SHA1withRSA(PKCSObjectIdentifiers.sha1WithRSAEncryption.getId()),
/** SHA-224 with RSA Signature Type */
SHA224withRSA(PKCSObjectIdentifiers.sha224WithRSAEncryption.getId()),
/** SHA-256 with RSA Signature Type */
SHA256withRSA(PKCSObjectIdentifiers.sha256WithRSAEncryption.getId()),
/** SHA-384 with RSA Signature Type */
SHA384withRSA(PKCSObjectIdentifiers.sha384WithRSAEncryption.getId()),
/** SHA-512 with RSA Signature Type */
SHA512withRSA(PKCSObjectIdentifiers.sha512WithRSAEncryption.getId()),
/** RIPEMD128 with RSA Signature Type */
RIPEMD128withRSA(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd128.getId()),
/** RIPEMD160 with RSA Signature Type */
RIPEMD160withRSA(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd160.getId()),
/** RIPEMD256 with RSA Signature Type */
RIPEMD256withRSA(TeleTrusTObjectIdentifiers.rsaSignatureWithripemd256.getId()),
/** SHA-1 with DSA Signature Type */
SHA1withDSA(X9ObjectIdentifiers.id_dsa_with_sha1.getId()),
/** SHA-224 with DSA signature type */
SHA224withDSA(NISTObjectIdentifiers.dsa_with_sha224.getId()),
/** SHA-256 with DSA signature type */
SHA256withDSA(NISTObjectIdentifiers.dsa_with_sha256.getId()),
/** SHA-384 with DSA signature type */
SHA384withDSA(NISTObjectIdentifiers.dsa_with_sha384.getId()),
/** SHA-512 with DSA signature type */
SHA512withDSA(NISTObjectIdentifiers.dsa_with_sha512.getId()),
/** SHA-1 with ECDSA Signature Type */
SHA1withECDSA(X9ObjectIdentifiers.ecdsa_with_SHA1.getId()),
/** SHA-224 with ECDSA Signature Type */
SHA224withECDSA(X9ObjectIdentifiers.ecdsa_with_SHA224.getId()),
/** SHA-256 with ECDSA Signature Type */
SHA256withECDSA(X9ObjectIdentifiers.ecdsa_with_SHA256.getId()),
/** SHA-384 with ECDSA Signature Type */
SHA384withECDSA(X9ObjectIdentifiers.ecdsa_with_SHA384.getId()),
/** SHA-512 with ECDSA Signature Type */
SHA512withECDSA(X9ObjectIdentifiers.ecdsa_with_SHA512.getId());
/** OID-to-type map */
private static final Map<String, SignatureType> OID_MAP;
static
{
HashMap<String, SignatureType> oidMap = new HashMap<String, SignatureType>();
for (SignatureType st : values())
{
oidMap.put(st.oid, st);
}
OID_MAP = Collections.unmodifiableMap(oidMap);
}
private static final Map<KeyPairType, Collection<SignatureType>> KEYPAIR_MAP;
static
{
HashMap<KeyPairType, Collection<SignatureType>> kpMap =
new HashMap<KeyPairType, Collection<SignatureType>>();
// X509V1CertificateGenerator doesn't like SHA384withDSA and SHA512withDSA as of BC 1.44
kpMap.put(KeyPairType.DSA,
Collections.unmodifiableSet(EnumSet.of(SHA1withDSA, SHA224withDSA, SHA256withDSA)));
kpMap.put(KeyPairType.RSA, Collections.unmodifiableSet(EnumSet.of(MD2withRSA, MD5withRSA,
SHA1withRSA, SHA224withRSA, SHA256withRSA, SHA384withRSA, SHA512withRSA, RIPEMD128withRSA,
RIPEMD160withRSA, RIPEMD256withRSA)));
kpMap.put(KeyPairType.ECDSA, Collections.unmodifiableSet(EnumSet.of(SHA1withECDSA, SHA224withECDSA,
SHA256withECDSA, SHA384withECDSA, SHA512withECDSA)));
KEYPAIR_MAP = Collections.unmodifiableMap(kpMap);
}
private final String oid;
private SignatureType(String oid)
{
this.oid = oid;
}
/**
* Gets supported signature types for given key pair type.
*
* @param keyPairType
* @return signature types for key pair type
*/
public static Collection<SignatureType> valuesFor(KeyPairType keyPairType)
{
Collection<SignatureType> values = KEYPAIR_MAP.get(keyPairType);
if (values == null)
{
values = Collections.emptySet();
}
return values;
}
/**
* Gets a default signature type for given key pair type.
*
* @param keyPairType
* @return default signature type for key pair type
*/
public static SignatureType defaultFor(KeyPairType keyPairType)
{
switch (keyPairType)
{
case RSA:
return SHA1withRSA;
case DSA:
return SHA1withDSA;
case ECDSA:
return SHA1withECDSA;
default:
return null;
}
}
/**
* Gets a SignatureType corresponding to the given object identifier.
*
* @param oid the object identifier
* @return the corresponding SignatureType, <code>null</code> if unknown
*/
public static SignatureType valueOfOid(String oid)
{
return OID_MAP.get(oid);
}
/**
* Gets a string representation of signature type corresponding to the given object identifier.
*
* @param oid the object identifier
* @return the corresponding signature type as string, <code>oid</code> itself if unknown
*/
public static String toString(String oid)
{
SignatureType type = valueOfOid(oid);
if (type != null)
{
return type.toString();
}
return oid;
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* StringUtil.java
*/
package org.maxkey.crypto.cert;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.Locale;
import org.bouncycastle.asn1.DERInteger;
/**
* String utilities.
*
* @author
*/
public class StringUtil
{
/**
* Convert the supplied object to hex characters sub-divided by spaces every given number of characters,
* and left-padded with zeros to fill group size.
*
* @param obj Object (byte array, BigInteger, DERInteger)
* @param groupSize number of characters to group hex characters by
* @param separator grouping separator
* @return Hex string
* @throws IllegalArgumentException if obj is not a BigInteger, byte array, or a DERInteger, or groupSize
* &lt; 0
*/
public static StringBuilder toHex(Object obj, int groupSize, String separator)
{
if (groupSize < 0)
{
throw new IllegalArgumentException("Group size must be >= 0");
}
BigInteger bigInt;
if (obj instanceof BigInteger)
{
bigInt = (BigInteger) obj;
}
else if (obj instanceof byte[])
{
bigInt = new BigInteger(1, (byte[]) obj);
}
else if (obj instanceof DERInteger)
{
bigInt = ((DERInteger) obj).getValue();
}
else
{
throw new IllegalArgumentException("Don't know how to convert " + obj.getClass().getName() +
" to a hex string");
}
// Convert to hex
StringBuilder sb = new StringBuilder(bigInt.toString(16).toUpperCase(Locale.ENGLISH));
// Left-pad if asked and necessary
if (groupSize != 0)
{
int len = groupSize - (sb.length() % groupSize);
if (len != groupSize)
{
for (int i = 0; i < len; i++)
{
sb.insert(0, '0');
}
}
}
// Place separator at every groupSize characters
if (sb.length() > groupSize && !separator.isEmpty())
{
for (int i = groupSize; i < sb.length(); i += groupSize + separator.length())
{
sb.insert(i, separator);
}
}
return sb;
}
// 1. String --> InputStream
public static InputStream String2InputStream(String str) {
ByteArrayInputStream stream = new ByteArrayInputStream(str.getBytes());
return stream;
}
// 2. InputStream --> String
public static String inputStream2String(InputStream is) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(is));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = in.readLine()) != null) {
buffer.append(line);
}
return buffer.toString();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,99 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* X509V3CertGen.java
*/
package org.maxkey.crypto.cert;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.Date;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.maxkey.crypto.KeyPairType;
import org.maxkey.crypto.KeyPairUtil;
/**
* Provides utility methods relating to X509 Certificates Gen
*/
public final class X509V3CertGen {
public static X509Certificate genV3Certificate(String issuerName,String subjectName,Date notBefore,Date notAfter,KeyPair keyPair) throws Exception {
//issuer same as subject is CA
BigInteger serial=BigInteger.valueOf(System.currentTimeMillis());
X500Name x500Name =new X500Name(issuerName);
X500Name subject =new X500Name(subjectName);
PublicKey publicKey =keyPair.getPublic();
PrivateKey privateKey=keyPair.getPrivate();
SubjectPublicKeyInfo subjectPublicKeyInfo = null;
try {
Object aiStream=new ASN1InputStream(publicKey.getEncoded()).readObject();
subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(aiStream);
} catch (IOException e1) {
e1.printStackTrace();
}
X509v3CertificateBuilder certBuilder = new X509v3CertificateBuilder(x500Name,
serial,
notBefore,
notAfter,
subject,
subjectPublicKeyInfo);
ContentSigner sigGen = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(privateKey);
//certBuilder.addExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));
//certBuilder.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature| KeyUsage.keyEncipherment));
//certBuilder.addExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeId.id_kp_serverAuth));
//certBuilder.addExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(new GeneralName(GeneralName.rfc822Name, "connsec@163.com")));
X509CertificateHolder x509CertificateHolder = certBuilder.build(sigGen);
CertificateFactory certificateFactory = CertificateFactory.class.newInstance();
InputStream inputStream = new ByteArrayInputStream(x509CertificateHolder.toASN1Structure().getEncoded());
X509Certificate x509Certificate = (X509Certificate) certificateFactory.engineGenerateCertificate(inputStream);
inputStream.close();
return x509Certificate;
}
public static KeyPair genRSAKeyPair() throws Exception {
return KeyPairUtil.genKeyPair(KeyPairType.RSA, "BC");
}
}

View File

@@ -0,0 +1,105 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
/**
*
*/
package org.maxkey.crypto.jose;
import com.google.common.base.Strings;
import com.nimbusds.jose.JWEAlgorithm;
/**
*
* Wrapper class for Nimbus JOSE objects to fit into JPA
*
* @author jricher
*
*/
public class JWEAlgorithmEmbed {
public static final JWEAlgorithmEmbed NONE = getForAlgorithmName("none");
private JWEAlgorithm algorithm;
public JWEAlgorithmEmbed() {
}
public JWEAlgorithmEmbed(JWEAlgorithm algorithm) {
this.algorithm = algorithm;
}
public static JWEAlgorithmEmbed getForAlgorithmName (String algorithmName) {
JWEAlgorithmEmbed ent = new JWEAlgorithmEmbed();
ent.setAlgorithmName(algorithmName);
if (ent.getAlgorithm() == null) {
return null;
} else {
return ent;
}
}
/**
* Get the name of this algorithm, return null if no algorithm set.
* @return
*/
public String getAlgorithmName() {
if (algorithm != null) {
return algorithm.getName();
} else {
return null;
}
}
/**
* Set the name of this algorithm.
* Calls JWEAlgorithm.parse()
* @param algorithmName
*/
public void setAlgorithmName(String algorithmName) {
if (!Strings.isNullOrEmpty(algorithmName)) {
algorithm = JWEAlgorithm.parse(algorithmName);
} else {
algorithm = null;
}
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "JWEAlgorithmEmbed [algorithm=" + algorithm + "]";
}
/**
* @return the algorithm
*/
public JWEAlgorithm getAlgorithm() {
return algorithm;
}
/**
* @param algorithm the algorithm to set
*/
public void setAlgorithm(JWEAlgorithm algorithm) {
this.algorithm = algorithm;
}
}

View File

@@ -0,0 +1,105 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
/**
*
*/
package org.maxkey.crypto.jose;
import com.google.common.base.Strings;
import com.nimbusds.jose.EncryptionMethod;
/**
* @author jricher
*
*/
public class JWEEncryptionMethodEmbed {
public static final JWEEncryptionMethodEmbed NONE = getForAlgorithmName("none");
private EncryptionMethod algorithm;
public JWEEncryptionMethodEmbed() {
}
public JWEEncryptionMethodEmbed(EncryptionMethod algorithm) {
this.algorithm = algorithm;
}
public static JWEEncryptionMethodEmbed getForAlgorithmName (String algorithmName) {
JWEEncryptionMethodEmbed ent = new JWEEncryptionMethodEmbed();
ent.setAlgorithmName(algorithmName);
if (ent.getAlgorithm() == null) {
return null;
} else {
return ent;
}
}
/**
* Get the name of this algorithm, return null if no algorithm set.
* @return
*/
public String getAlgorithmName() {
if (algorithm != null) {
return algorithm.getName();
} else {
return null;
}
}
/**
* Set the name of this algorithm.
* Calls EncryptionMethod.parse()
* @param algorithmName
*/
public void setAlgorithmName(String algorithmName) {
if (!Strings.isNullOrEmpty(algorithmName)) {
algorithm = EncryptionMethod.parse(algorithmName);
} else {
algorithm = null;
}
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "JWEEncryptionMethodEmbed [algorithm=" + algorithm + "]";
}
/**
* @return the algorithm
*/
public EncryptionMethod getAlgorithm() {
return algorithm;
}
/**
* @param algorithm the algorithm to set
*/
public void setAlgorithm(EncryptionMethod algorithm) {
this.algorithm = algorithm;
}
}

View File

@@ -0,0 +1,113 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
/**
*
*/
package org.maxkey.crypto.jose;
import com.google.common.base.Strings;
import com.nimbusds.jose.JWSAlgorithm;
/**
*
* Wrapper class for Nimbus JOSE objects to fit into JPA
*
* @author jricher
*
*/
public class JWSAlgorithmEmbed {
public static final JWSAlgorithmEmbed NONE = getForAlgorithmName("none");
private JWSAlgorithm algorithm;
public JWSAlgorithmEmbed() {
}
public JWSAlgorithmEmbed(JWSAlgorithm algorithm) {
this.algorithm = algorithm;
}
/**
*
* @param algorithmName
* @return null if algorithmName is empty or null
*/
public static JWSAlgorithmEmbed getForAlgorithmName (String algorithmName) {
JWSAlgorithmEmbed ent = new JWSAlgorithmEmbed();
ent.setAlgorithmName(algorithmName);
if (ent.getAlgorithm() == null) {
return null;
} else {
return ent;
}
}
/**
* Get the name of this algorithm, return null if no algorithm set.
* @return
*/
public String getAlgorithmName() {
if (algorithm != null) {
return algorithm.getName();
} else {
return null;
}
}
/**
* Set the name of this algorithm.
* Calls JWSAlgorithm.parse()
* @param algorithmName
*/
public void setAlgorithmName(String algorithmName) {
if (!Strings.isNullOrEmpty(algorithmName)) {
algorithm = JWSAlgorithm.parse(algorithmName);
} else {
algorithm = null;
}
}
/**
* @return the algorithm
*/
public JWSAlgorithm getAlgorithm() {
return algorithm;
}
/**
* @param algorithm the algorithm to set
*/
public void setAlgorithm(JWSAlgorithm algorithm) {
this.algorithm = algorithm;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "JWSAlgorithmEmbed [algorithm=" + algorithm + "]";
}
}

View File

@@ -0,0 +1,125 @@
package org.maxkey.crypto.jose.keystore;
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKSet;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
/**
* .
* @author jricher
*
*/
public class JWKSetKeyStore {
private static final Logger _logger = LoggerFactory.getLogger(JWKSetKeyStore.class);
private JWKSet jwkSet;
private Resource location;
public JWKSetKeyStore() {
}
public JWKSetKeyStore(JWKSet jwkSet) {
this.jwkSet = jwkSet;
initializeJwkSet();
}
private void initializeJwkSet() {
if (jwkSet == null) {
if (location != null) {
if (location.exists() && location.isReadable()) {
try {
_logger.debug("JWK location " + location.getURL());
// read in the file from disk
String s = CharStreams
.toString(new InputStreamReader(location.getInputStream(), Charsets.UTF_8));
// parse it into a jwkSet object
jwkSet = JWKSet.parse(s);
} catch (IOException e) {
throw new IllegalArgumentException("Key Set resource could not be read: " + location);
} catch (ParseException e) {
throw new IllegalArgumentException("Key Set resource could not be parsed: " + location);
}
} else {
throw new IllegalArgumentException("Key Set resource could not be read: " + location);
}
} else {
throw new IllegalArgumentException(
"Key store must be initialized with at least one of a jwkSet or a location.");
}
}
}
/**
* @return the jwkSet
*/
public JWKSet getJwkSet() {
return jwkSet;
}
/**
* @param jwkSet the jwkSet to set
*/
public void setJwkSet(JWKSet jwkSet) {
this.jwkSet = jwkSet;
initializeJwkSet();
}
/**
* @return the location
*/
public Resource getLocation() {
return location;
}
/**
* @param location the location to set
*/
public void setLocation(Resource location) {
this.location = location;
initializeJwkSet();
}
/**
* Get the list of keys in this keystore. This is a passthrough to the
* underlying JWK Set
*/
public List<JWK> getKeys() {
if (jwkSet == null) {
initializeJwkSet();
}
return jwkSet.getKeys();
}
}

View File

@@ -0,0 +1,70 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.maxkey.crypto.jwt.encryption.service;
import java.util.Collection;
import java.util.Map;
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWEObject;
import com.nimbusds.jose.jwk.JWK;
/**
* @author wkim
*
*/
public interface JwtEncryptionAndDecryptionService {
/**
* Encrypts the JWT in place with the default encrypter.
* If an arbitrary payload is used, then pass in a JWEObject.
* Otherwise, if JWT claims are the payload, then use the JWEObject subclass EncryptedJWT instead.
* @param jwt
*/
public void encryptJwt(JWEObject jwt);
/**
* Decrypts the JWT in place with the default decrypter.
* If an arbitrary payload is used, then pass in a JWEObject.
* Otherwise, if JWT claims are the payload, then use the JWEObject subclass EncryptedJWT instead.
* @param jwt
*/
public void decryptJwt(JWEObject jwt);
/**
* Get all public keys for this service, mapped by their Key ID
*/
public Map<String, JWK> getAllPublicKeys();
/**
* Get the list of all encryption algorithms supported by this service.
* @return
*/
public Collection<JWEAlgorithm> getAllEncryptionAlgsSupported();
/**
* Get the list of all encryption methods supported by this service.
* @return
*/
public Collection<EncryptionMethod> getAllEncryptionEncsSupported();
/**
* TODO add functionality for encrypting and decrypting using a specified key id.
* Example: public void encryptJwt(EncryptedJWT jwt, String kid);
*/
}

View File

@@ -0,0 +1,301 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.maxkey.crypto.jwt.encryption.service.impl;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import org.maxkey.crypto.jose.keystore.JWKSetKeyStore;
import org.maxkey.crypto.jwt.encryption.service.JwtEncryptionAndDecryptionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Strings;
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWEDecrypter;
import com.nimbusds.jose.JWEEncrypter;
import com.nimbusds.jose.JWEObject;
import com.nimbusds.jose.crypto.DirectDecrypter;
import com.nimbusds.jose.crypto.DirectEncrypter;
import com.nimbusds.jose.crypto.RSADecrypter;
import com.nimbusds.jose.crypto.RSAEncrypter;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.OctetSequenceKey;
import com.nimbusds.jose.jwk.RSAKey;
/**
* @author wkim
*
*/
public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAndDecryptionService {
private static Logger logger = LoggerFactory.getLogger(DefaultJwtEncryptionAndDecryptionService.class);
// map of identifier to encrypter
private Map<String, JWEEncrypter> encrypters = new HashMap<String, JWEEncrypter>();
// map of identifier to decrypter
private Map<String, JWEDecrypter> decrypters = new HashMap<String, JWEDecrypter>();
private String defaultEncryptionKeyId;
private String defaultDecryptionKeyId;
private JWEAlgorithm defaultAlgorithm;
// map of identifier to key
private Map<String, JWK> keys = new HashMap<String, JWK>();
/**
* Build this service based on the keys given. All public keys will be used to make encrypters,
* all private keys will be used to make decrypters.
*
* @param keys
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws JOSEException
*/
public DefaultJwtEncryptionAndDecryptionService(Map<String, JWK> keys) throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
this.keys = keys;
buildEncryptersAndDecrypters();
}
/**
* Build this service based on the given keystore. All keys must have a key
* id ({@code kid}) field in order to be used.
*
* @param keyStore
* @throws NoSuchAlgorithmException
* @throws InvalidKeySpecException
* @throws JOSEException
*/
public DefaultJwtEncryptionAndDecryptionService(JWKSetKeyStore keyStore) throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
// convert all keys in the keystore to a map based on key id
for (JWK key : keyStore.getKeys()) {
if (!Strings.isNullOrEmpty(key.getKeyID())) {
this.keys.put(key.getKeyID(), key);
} else {
throw new IllegalArgumentException("Tried to load a key from a keystore without a 'kid' field: " + key);
}
}
buildEncryptersAndDecrypters();
}
@PostConstruct
public void afterPropertiesSet() {
if (keys == null) {
throw new IllegalArgumentException("Encryption and decryption service must have at least one key configured.");
}
try {
buildEncryptersAndDecrypters();
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException("Encryption and decryption service could not find given algorithm.");
} catch (InvalidKeySpecException e) {
throw new IllegalArgumentException("Encryption and decryption service saw an invalid key specification.");
} catch (JOSEException e) {
throw new IllegalArgumentException("Encryption and decryption service was unable to process JOSE object.");
}
}
public String getDefaultEncryptionKeyId() {
if (defaultEncryptionKeyId != null) {
return defaultEncryptionKeyId;
} else if (keys.size() == 1) {
// if there's only one key in the map, it's the default
return keys.keySet().iterator().next();
} else {
return null;
}
}
public void setDefaultEncryptionKeyId(String defaultEncryptionKeyId) {
this.defaultEncryptionKeyId = defaultEncryptionKeyId;
}
public String getDefaultDecryptionKeyId() {
if (defaultDecryptionKeyId != null) {
return defaultDecryptionKeyId;
} else if (keys.size() == 1) {
// if there's only one key in the map, it's the default
return keys.keySet().iterator().next();
} else {
return null;
}
}
public void setDefaultDecryptionKeyId(String defaultDecryptionKeyId) {
this.defaultDecryptionKeyId = defaultDecryptionKeyId;
}
public JWEAlgorithm getDefaultAlgorithm() {
return defaultAlgorithm;
}
public void setDefaultAlgorithm(JWEAlgorithm defaultAlgorithm) {
this.defaultAlgorithm = defaultAlgorithm;
}
/* (non-Javadoc)
* @see org.mitre.jwt.encryption.service.JwtEncryptionAndDecryptionService#encryptJwt(com.nimbusds.jwt.EncryptedJWT)
*/
@Override
public void encryptJwt(JWEObject jwt) {
if (getDefaultEncryptionKeyId() == null) {
throw new IllegalStateException("Tried to call default encryption with no default encrypter ID set");
}
JWEEncrypter encrypter = encrypters.get(getDefaultEncryptionKeyId());
try {
jwt.encrypt(encrypter);
} catch (JOSEException e) {
logger.error("Failed to encrypt JWT, error was: ", e);
}
}
/* (non-Javadoc)
* @see org.mitre.jwt.encryption.service.JwtEncryptionAndDecryptionService#decryptJwt(com.nimbusds.jwt.EncryptedJWT)
*/
@Override
public void decryptJwt(JWEObject jwt) {
if (getDefaultDecryptionKeyId() == null) {
throw new IllegalStateException("Tried to call default decryption with no default decrypter ID set");
}
JWEDecrypter decrypter = decrypters.get(getDefaultDecryptionKeyId());
try {
jwt.decrypt(decrypter);
} catch (JOSEException e) {
logger.error("Failed to decrypt JWT, error was: ", e);
}
}
/**
* Builds all the encrypters and decrypters for this service based on the key map.
* @throws
* @throws InvalidKeySpecException
* @throws NoSuchAlgorithmException
* @throws JOSEException
*/
private void buildEncryptersAndDecrypters() throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
for (Map.Entry<String, JWK> jwkEntry : keys.entrySet()) {
String id = jwkEntry.getKey();
JWK jwk = jwkEntry.getValue();
if (jwk instanceof RSAKey) {
// build RSA encrypters and decrypters
RSAEncrypter encrypter = new RSAEncrypter(((RSAKey) jwk).toRSAPublicKey()); // there should always at least be the public key
encrypters.put(id, encrypter);
if (jwk.isPrivate()) { // we can decrypt!
RSADecrypter decrypter = new RSADecrypter(((RSAKey) jwk).toRSAPrivateKey());
decrypters.put(id, decrypter);
} else {
logger.warn("No private key for key #" + jwk.getKeyID());
}
// TODO: add support for EC keys
} else if (jwk instanceof OctetSequenceKey) {
// build symmetric encrypters and decrypters
DirectEncrypter encrypter = new DirectEncrypter(((OctetSequenceKey) jwk).toByteArray());
DirectDecrypter decrypter = new DirectDecrypter(((OctetSequenceKey) jwk).toByteArray());
encrypters.put(id, encrypter);
decrypters.put(id, decrypter);
} else {
logger.warn("Unknown key type: " + jwk);
}
}
}
@Override
public Map<String, JWK> getAllPublicKeys() {
Map<String, JWK> pubKeys = new HashMap<String, JWK>();
// pull out all public keys
for (String keyId : keys.keySet()) {
JWK key = keys.get(keyId);
JWK pub = key.toPublicJWK();
if (pub != null) {
pubKeys.put(keyId, pub);
}
}
return pubKeys;
}
@Override
public Collection<JWEAlgorithm> getAllEncryptionAlgsSupported() {
Set<JWEAlgorithm> algs = new HashSet<JWEAlgorithm>();
for (JWEEncrypter encrypter : encrypters.values()) {
algs.addAll(encrypter.supportedJWEAlgorithms());
}
for (JWEDecrypter decrypter : decrypters.values()) {
algs.addAll(decrypter.supportedJWEAlgorithms());
}
return algs;
}
/* (non-Javadoc)
* @see org.mitre.jwt.encryption.service.JwtEncryptionAndDecryptionService#getAllEncryptionEncsSupported()
*/
@Override
public Collection<EncryptionMethod> getAllEncryptionEncsSupported() {
Set<EncryptionMethod> encs = new HashSet<EncryptionMethod>();
for (JWEEncrypter encrypter : encrypters.values()) {
encs.addAll(encrypter.supportedEncryptionMethods());
}
for (JWEDecrypter decrypter : decrypters.values()) {
encs.addAll(decrypter.supportedEncryptionMethods());
}
return encs;
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.crypto.jwt.encryption.service.impl;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.text.ParseException;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.log4j.Logger;
import org.maxkey.crypto.jose.keystore.JWKSetKeyStore;
import org.maxkey.crypto.jwt.encryption.service.JwtEncryptionAndDecryptionService;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.jwk.JWKSet;
/**
* @author Crystal.Sea
*
*/
public class RecipientJwtEncryptionAndDecryptionServiceBuilder {
final static Logger logger = Logger.getLogger(RecipientJwtEncryptionAndDecryptionServiceBuilder.class);
//private HttpClient httpClient = HttpClientBuilder.create().useSystemProperties().build();
//private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
//private RestTemplate restTemplate = new RestTemplate(httpFactory);
/**
*
*/
public RecipientJwtEncryptionAndDecryptionServiceBuilder() {
}
public JwtEncryptionAndDecryptionService serviceBuilder(String jwksUri){
logger.debug("jwksUri : "+jwksUri);
String jsonString ="";//= restTemplate.getForObject(jwksUri, String.class);
logger.debug("jwks json String : "+jsonString);
JwtEncryptionAndDecryptionService recipientJwtEncryptionAndDecryptionService;
try {
JWKSet jwkSet = JWKSet.parse(jsonString);
JWKSetKeyStore keyStore = new JWKSetKeyStore(jwkSet);
recipientJwtEncryptionAndDecryptionService = new DefaultJwtEncryptionAndDecryptionService(keyStore);
return recipientJwtEncryptionAndDecryptionService;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (JOSEException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}

View File

@@ -0,0 +1,82 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.maxkey.crypto.jwt.signer.service;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.Map;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jwt.SignedJWT;
public interface JwtSigningAndValidationService {
/**
* Get all public keys for this service, mapped by their Key ID
*/
public Map<String, JWK> getAllPublicKeys();
/**
* Checks the signature of the given JWT against all configured signers,
* returns true if at least one of the signers validates it.
*
* @param jwtString
* the string representation of the JWT as sent on the wire
* @return true if the signature is valid, false if not
* @throws NoSuchAlgorithmException
*/
public boolean validateSignature(SignedJWT jwtString);
/**
* Called to sign a jwt in place for a client that hasn't registered a preferred signing algorithm.
* Use the default algorithm to sign.
*
* @param jwt the jwt to sign
* @return the signed jwt
* @throws NoSuchAlgorithmException
*/
public void signJwt(SignedJWT jwt);
/**
* Get the default signing algorithm for use when nothing else has been specified.
* @return
*/
public JWSAlgorithm getDefaultSigningAlgorithm();
/**
* Get the list of all signing algorithms supported by this service.
* @return
*/
public Collection<JWSAlgorithm> getAllSigningAlgsSupported();
/**
* Sign a jwt using the selected algorithm. The algorithm is selected using the String parameter values specified
* in the JWT spec, section 6. I.E., "HS256" means HMAC with SHA-256 and corresponds to our HmacSigner class.
*
* @param jwt the jwt to sign
* @param alg the name of the algorithm to use, as specified in JWS s.6
* @return the signed jwt
*/
public void signJwt(SignedJWT jwt, JWSAlgorithm alg);
public String getDefaultSignerKeyId();
/**
* TODO: method to sign a jwt using a specified algorithm and a key id
*/
}

View File

@@ -0,0 +1,300 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.maxkey.crypto.jwt.signer.service.impl;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.maxkey.crypto.jose.keystore.JWKSetKeyStore;
import org.maxkey.crypto.jwt.signer.service.JwtSigningAndValidationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Strings;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jose.jwk.ECKey;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.OctetSequenceKey;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.SignedJWT;
public class DefaultJwtSigningAndValidationService implements JwtSigningAndValidationService {
// map of identifier to signer
private Map<String, JWSSigner> signers = new HashMap<String, JWSSigner>();
// map of identifier to verifier
private Map<String, JWSVerifier> verifiers = new HashMap<String, JWSVerifier>();
private static Logger logger = LoggerFactory.getLogger(DefaultJwtSigningAndValidationService.class);
private String defaultSignerKeyId;
private JWSAlgorithm defaultAlgorithm;
// map of identifier to key
private Map<String, JWK> keys = new HashMap<String, JWK>();
/**
* Build this service based on the keys given. All public keys will be used
* to make verifiers, all private keys will be used to make signers.
*
* @param keys
* A map of key identifier to key
*
* @throws InvalidKeySpecException
* If the keys in the JWKs are not valid
* @throws NoSuchAlgorithmException
* If there is no appropriate algorithm to tie the keys to.
* @throws JOSEException
*/
public DefaultJwtSigningAndValidationService(Map<String, JWK> keys) throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
this.keys = keys;
buildSignersAndVerifiers();
}
/**
* Build this service based on the given keystore. All keys must have a key
* id ({@code kid}) field in order to be used.
*
* @param keyStore
* the keystore to load all keys from
*
* @throws InvalidKeySpecException
* If the keys in the JWKs are not valid
* @throws NoSuchAlgorithmException
* If there is no appropriate algorithm to tie the keys to.
* @throws JOSEException
*/
public DefaultJwtSigningAndValidationService(JWKSetKeyStore keyStore) throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
// convert all keys in the keystore to a map based on key id
if (keyStore!= null && keyStore.getJwkSet() != null) {
for (JWK key : keyStore.getKeys()) {
if (!Strings.isNullOrEmpty(key.getKeyID())) {
// use the key ID that's built into the key itself
// TODO (#641): deal with JWK thumbprints
this.keys.put(key.getKeyID(), key);
} else {
// create a random key id
String fakeKid = UUID.randomUUID().toString();
this.keys.put(fakeKid, key);
}
}
}
buildSignersAndVerifiers();
}
/**
* @return the defaultSignerKeyId
*/
@Override
public String getDefaultSignerKeyId() {
return defaultSignerKeyId;
}
/**
* @param defaultSignerKeyId the defaultSignerKeyId to set
*/
public void setDefaultSignerKeyId(String defaultSignerId) {
this.defaultSignerKeyId = defaultSignerId;
}
/**
* @return
*/
@Override
public JWSAlgorithm getDefaultSigningAlgorithm() {
return defaultAlgorithm;
}
public void setDefaultSigningAlgorithmName(String algName) {
defaultAlgorithm = JWSAlgorithm.parse(algName);
}
public String getDefaultSigningAlgorithmName() {
if (defaultAlgorithm != null) {
return defaultAlgorithm.getName();
} else {
return null;
}
}
/**
* Build all of the signers and verifiers for this based on the key map.
* @throws InvalidKeySpecException If the keys in the JWKs are not valid
* @throws NoSuchAlgorithmException If there is no appropriate algorithm to tie the keys to.
* @throws JOSEException
*/
private void buildSignersAndVerifiers() throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
for (Map.Entry<String, JWK> jwkEntry : keys.entrySet()) {
String id = jwkEntry.getKey();
JWK jwk = jwkEntry.getValue();
if (jwk instanceof RSAKey) {
// build RSA signers & verifiers
if (jwk.isPrivate()) { // only add the signer if there's a private key
RSASSASigner signer = new RSASSASigner(((RSAKey) jwk).toRSAPrivateKey());
signers.put(id, signer);
}
RSASSAVerifier verifier = new RSASSAVerifier(((RSAKey) jwk).toRSAPublicKey());
verifiers.put(id, verifier);
} else if (jwk instanceof ECKey) {
// build EC signers & verifiers
// TODO: add support for EC keys
logger.warn("EC Keys are not yet supported.");
} else if (jwk instanceof OctetSequenceKey) {
// build HMAC signers & verifiers
if (jwk.isPrivate()) { // technically redundant check because all HMAC keys are private
MACSigner signer = new MACSigner(((OctetSequenceKey) jwk).toByteArray());
signers.put(id, signer);
}
MACVerifier verifier = new MACVerifier(((OctetSequenceKey) jwk).toByteArray());
verifiers.put(id, verifier);
} else {
logger.warn("Unknown key type: " + jwk);
}
}
if (defaultSignerKeyId == null && keys.size() == 1) {
// if there's only one key, it's the default
setDefaultSignerKeyId(keys.keySet().iterator().next());
}
}
/**
* Sign a jwt in place using the configured default signer.
*/
@Override
public void signJwt(SignedJWT jwt) {
if (getDefaultSignerKeyId() == null) {
throw new IllegalStateException("Tried to call default signing with no default signer ID set");
}
JWSSigner signer = signers.get(getDefaultSignerKeyId());
try {
jwt.sign(signer);
} catch (JOSEException e) {
logger.error("Failed to sign JWT, error was: ", e);
}
}
@Override
public void signJwt(SignedJWT jwt, JWSAlgorithm alg) {
JWSSigner signer = null;
for (JWSSigner s : signers.values()) {
if (s.supportedJWSAlgorithms().contains(alg)) {
signer = s;
break;
}
}
if (signer == null) {
//If we can't find an algorithm that matches, we can't sign
logger.error("No matching algirthm found for alg=" + alg);
}
try {
jwt.sign(signer);
} catch (JOSEException e) {
logger.error("Failed to sign JWT, error was: ", e);
}
}
@Override
public boolean validateSignature(SignedJWT jwt) {
for (JWSVerifier verifier : verifiers.values()) {
try {
if (jwt.verify(verifier)) {
return true;
}
} catch (JOSEException e) {
logger.error("Failed to validate signature, error was: ", e);
}
}
return false;
}
@Override
public Map<String, JWK> getAllPublicKeys() {
Map<String, JWK> pubKeys = new HashMap<String, JWK>();
// pull all keys out of the verifiers if we know how
for (String keyId : keys.keySet()) {
JWK key = keys.get(keyId);
JWK pub = key.toPublicJWK();
if (pub != null) {
pubKeys.put(keyId, pub);
}
}
return pubKeys;
}
/* (non-Javadoc)
* @see org.mitre.jwt.signer.service.JwtSigningAndValidationService#getAllSigningAlgsSupported()
*/
@Override
public Collection<JWSAlgorithm> getAllSigningAlgsSupported() {
Set<JWSAlgorithm> algs = new HashSet<JWSAlgorithm>();
for (JWSSigner signer : signers.values()) {
algs.addAll(signer.supportedJWSAlgorithms());
}
for (JWSVerifier verifier : verifiers.values()) {
algs.addAll(verifier.supportedJWSAlgorithms());
}
return algs;
}
}

View File

@@ -0,0 +1,155 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
/**
*
*/
package org.maxkey.crypto.jwt.signer.service.impl;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.maxkey.crypto.jose.keystore.JWKSetKeyStore;
import org.maxkey.crypto.jwt.encryption.service.JwtEncryptionAndDecryptionService;
import org.maxkey.crypto.jwt.encryption.service.impl.DefaultJwtEncryptionAndDecryptionService;
import org.maxkey.crypto.jwt.signer.service.JwtSigningAndValidationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.nimbusds.jose.jwk.JWKSet;
/**
*
* Creates a caching map of JOSE signers/validators and encrypters/decryptors
* keyed on the JWK Set URI. Dynamically loads JWK Sets to create the services.
*
* @author jricher
*
*/
@Service
public class JWKSetCacheService {
private static Logger logger = LoggerFactory.getLogger(JWKSetCacheService.class);
// map of jwk set uri -> signing/validation service built on the keys found in that jwk set
private LoadingCache<String, JwtSigningAndValidationService> validators;
// map of jwk set uri -> encryption/decryption service built on the keys found in that jwk set
private LoadingCache<String, JwtEncryptionAndDecryptionService> encrypters;
public JWKSetCacheService() {
this.validators = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS) // expires 1 hour after fetch
.maximumSize(100)
.build(new JWKSetVerifierFetcher());
this.encrypters = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS) // expires 1 hour after fetch
.maximumSize(100)
.build(new JWKSetEncryptorFetcher());
}
/**
* @param jwksUri
* @return
* @throws ExecutionException
* @see com.google.common.cache.Cache#get(java.lang.Object)
*/
public JwtSigningAndValidationService getValidator(String jwksUri) {
try {
return validators.get(jwksUri);
} catch (UncheckedExecutionException ue) {
logger.warn("Couldn't load JWK Set from " + jwksUri, ue);
return null;
} catch (ExecutionException e) {
logger.warn("Couldn't load JWK Set from " + jwksUri, e);
return null;
}
}
public JwtEncryptionAndDecryptionService getEncrypter(String jwksUri) {
try {
return encrypters.get(jwksUri);
} catch (UncheckedExecutionException ue) {
logger.warn("Couldn't load JWK Set from " + jwksUri, ue);
return null;
} catch (ExecutionException e) {
logger.warn("Couldn't load JWK Set from " + jwksUri, e);
return null;
}
}
/**
* @author jricher
*
*/
private class JWKSetVerifierFetcher extends CacheLoader<String, JwtSigningAndValidationService> {
private HttpClient httpClient = HttpClientBuilder.create().useSystemProperties().build();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private RestTemplate restTemplate = new RestTemplate(httpFactory);
/**
* Load the JWK Set and build the appropriate signing service.
*/
@Override
public JwtSigningAndValidationService load(String key) throws Exception {
String jsonString = restTemplate.getForObject(key, String.class);
JWKSet jwkSet = JWKSet.parse(jsonString);
JWKSetKeyStore keyStore = new JWKSetKeyStore(jwkSet);
JwtSigningAndValidationService service = new DefaultJwtSigningAndValidationService(keyStore);
return service;
}
}
/**
* @author jricher
*
*/
private class JWKSetEncryptorFetcher extends CacheLoader<String, JwtEncryptionAndDecryptionService> {
private HttpClient httpClient = HttpClientBuilder.create().useSystemProperties().build();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private RestTemplate restTemplate = new RestTemplate(httpFactory);
/* (non-Javadoc)
* @see com.google.common.cache.CacheLoader#load(java.lang.Object)
*/
@Override
public JwtEncryptionAndDecryptionService load(String key) throws Exception {
String jsonString = restTemplate.getForObject(key, String.class);
JWKSet jwkSet = JWKSet.parse(jsonString);
JWKSetKeyStore keyStore = new JWKSetKeyStore(jwkSet);
JwtEncryptionAndDecryptionService service = new DefaultJwtEncryptionAndDecryptionService(keyStore);
return service;
}
}
}

View File

@@ -0,0 +1,118 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.maxkey.crypto.jwt.signer.service.impl;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.maxkey.crypto.jwt.signer.service.JwtSigningAndValidationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.google.common.base.Strings;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.OctetSequenceKey;
import com.nimbusds.jose.util.Base64URL;
/**
* Creates and caches symmetrical validators for clients based on client secrets.
*
* @author jricher
*
*/
@Service
public class SymmetricCacheService {
private static Logger logger = LoggerFactory.getLogger(SymmetricCacheService.class);
private LoadingCache<String, JwtSigningAndValidationService> validators;
public SymmetricCacheService() {
validators = CacheBuilder.newBuilder()
.expireAfterAccess(24, TimeUnit.HOURS)
.maximumSize(100)
.build(new SymmetricValidatorBuilder());
}
/**
* Create a symmetric signing and validation service for the given client
*
* @param client
* @return
*/
public JwtSigningAndValidationService getSymmetricValidtor(String clientSecret) {
if (clientSecret == null) {
logger.error("Couldn't create symmetric validator for null client");
return null;
}
if (Strings.isNullOrEmpty(clientSecret)) {
logger.error("Couldn't create symmetric validator for client without a client secret");
return null;
}
try {
return validators.get(clientSecret);
} catch (UncheckedExecutionException ue) {
logger.error("Problem loading client validator", ue);
return null;
} catch (ExecutionException e) {
logger.error("Problem loading client validator", e);
return null;
}
}
public class SymmetricValidatorBuilder extends CacheLoader<String, JwtSigningAndValidationService> {
@Override
public JwtSigningAndValidationService load(String key) throws Exception {
try {
String id = "SYMMETRIC-KEY";
//TODO:
JWK jwk =null;
//JWK jwk = new OctetSequenceKey(Base64URL.encode(key), KeyUse.SIGNATURE, null, null, id, null, null, null);
Map<String, JWK> keys = ImmutableMap.of(id, jwk);
JwtSigningAndValidationService service = new DefaultJwtSigningAndValidationService(keys);
return service;
} catch (NoSuchAlgorithmException e) {
logger.error("Couldn't create symmetric validator for client", e);
} catch (InvalidKeySpecException e) {
logger.error("Couldn't create symmetric validator for client", e);
}
throw new IllegalArgumentException("Couldn't create symmetric validator for client");
}
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.crypto.jwt.signer.service.impl;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Map;
import org.apache.log4j.Logger;
import org.maxkey.crypto.jwt.signer.service.JwtSigningAndValidationService;
import com.google.common.collect.ImmutableMap;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.OctetSequenceKey;
import com.nimbusds.jose.util.Base64URL;
/**
* @author Crystal.Sea
* Builder Symmetric Signing Service
*/
public class SymmetricSigningAndValidationServiceBuilder {
final static Logger logger = Logger.getLogger(SymmetricSigningAndValidationServiceBuilder.class);
public static final String SYMMETRIC_KEY = "SYMMETRIC-KEY";
/**
*
*/
public SymmetricSigningAndValidationServiceBuilder() {
}
public JwtSigningAndValidationService serviceBuilder(String sharedSecret){
logger.debug("shared Secret : "+sharedSecret);
logger.debug("Symmetric Id : "+SYMMETRIC_KEY);
if (sharedSecret == null) {
logger.error("Couldn't create symmetric SigningAndValidation");
return null;
}
/**
* Builder Symmetric Signing And Validation Service
*/
//TODO:
JWK jwk = null;
//JWK jwk = new OctetSequenceKey(Base64URL.encode(sharedSecret), KeyUse.SIGNATURE, null, null, SYMMETRIC_KEY, null, null, null);
Map<String, JWK> keys = ImmutableMap.of(SYMMETRIC_KEY, jwk);
try {
JwtSigningAndValidationService symmetricSigningAndValidationService = new DefaultJwtSigningAndValidationService(keys);
return symmetricSigningAndValidationService;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (JOSEException e) {
e.printStackTrace();
}
return null;
}
}

View File

@@ -0,0 +1,139 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.crypto.keystore;
import java.security.KeyStore;
import java.util.Enumeration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.ResourceUtils;
/**
* .
* @author Crystal.Sea
*
*/
public class KeyStoreLoader implements InitializingBean {
private static final Logger _logger = LoggerFactory.getLogger(KeyStoreLoader.class);
private KeyStore keyStore;
private String entityName;
private Resource keystoreFile;
private String keystorePassword;
private String keystoreType = "JKS";
/**
*
*/
public KeyStoreLoader() {
}
/**
* @return the keyStore
*/
public KeyStore getKeyStore() {
return keyStore;
}
/**
* @param keystoreFile the keystoreFile to set
*/
public void setKeystoreFile(Resource keystoreFile) {
this.keystoreFile = keystoreFile;
}
/**
* @param keystorePassword the keystorePassword to set
*/
public void setKeystorePassword(String keystorePassword) {
this.keystorePassword = keystorePassword;
}
/**
* <20><>ȡKeyStore<72><65><EFBFBD><EFBFBD>
*
* @return
*/
public String getKeystorePassword() {
return keystorePassword;
}
@Override
public void afterPropertiesSet() throws Exception {
_logger.debug("Load KeyStore from file " + keystoreFile.getURL());
keyStore = KeyStoreUtil.loadKeyStore(
keystoreFile, keystorePassword.toCharArray(),
KeyStoreType.JKS);
_logger.debug("Load KeyStore success . ");
Enumeration<String> temp = keyStore.aliases();
int i = 0;
while (temp.hasMoreElements()) {
_logger.debug("KeyStore alias name " + (i++) + " : " + temp.nextElement());
}
}
/**
* .
* @return the entityName
*/
public String getEntityName() {
return entityName;
}
/**
* @param entityName the entityName to set
*/
public void setEntityName(String entityName) {
this.entityName = entityName;
}
/**
* @return the keystoreType
*/
public String getKeystoreType() {
return keystoreType;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("KeyStoreLoader [keyStore=");
builder.append(keyStore);
builder.append(", entityName=");
builder.append(entityName);
builder.append(", keystoreFile=");
builder.append(keystoreFile);
builder.append(", keystorePassword=");
builder.append(keystorePassword);
builder.append(", keystoreType=");
builder.append(keystoreType);
builder.append("]");
return builder.toString();
}
}

View File

@@ -0,0 +1,154 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* KeyStoreType.java
*/
package org.maxkey.crypto.keystore;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* KeyStore type. Enum constant names are compatible with JCA names.
*
* @see <a
* href="http://download.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html">JCA
* Standard Names</a>
*/
public enum KeyStoreType {
/** JKS keystore Type */
JKS("JKS", true, true, new String[] { "jks" }),
/** PKCS #12 keystore Type */
PKCS12("PKCS #12", false, false, new String[] { "p12", "pfx" }),
/** JCEKS keystore Type */
JCEKS("JCEKS", true, true, new String[] { "jceks" }),
/** Case sensitive JKS keystore Type */
CaseExactJKS("JKS (case sensitive)", true, true, new String[] { "jks" }),
/** BKS keystore Type */
BKS("BKS", true, true, new String[] { "bks" }),
/** UBER keystore Type */
UBER("UBER", true, true, new String[] { "ubr" }),
/** GKR keystore Type */
GKR("GKR", true, true, new String[] { "gkr" }),
/** PKCS #11 keystore Type */
PKCS11("PKCS #11", false, true, new String[0]);
/** Keystore "pretty" name */
private final String prettyName;
/**
* Whether the keystore type provides useful values for entry creation dates
*/
private final boolean entryCreationDateUseful;
/** Whether the keystore supports entry passwords */
private final boolean entryPasswordSupported;
/** Associated filename extensions */
private final Set<String> filenameExtensions;
/**
* Construct a KeyStoreType. Private to prevent construction from outside
* this class.
*
* @param sType
* Keystore type
* @param supportsCreationDates
* Whether the keystore supports creation dates
* @param filenameExtensions
* associated filename extensions
*/
private KeyStoreType(String prettyName, boolean entryCreationDateUseful,
boolean entryPasswordSupported, String[] filenameExtensions) {
this.prettyName = prettyName;
this.entryCreationDateUseful = entryCreationDateUseful;
this.entryPasswordSupported = entryPasswordSupported;
switch (filenameExtensions.length) {
case 0:
this.filenameExtensions = Collections.emptySet();
break;
case 1:
this.filenameExtensions = Collections
.singleton(filenameExtensions[0]);
break;
default:
LinkedHashSet<String> exts = new LinkedHashSet<String>(
filenameExtensions.length);
Collections.addAll(exts, filenameExtensions);
this.filenameExtensions = Collections.unmodifiableSet(exts);
}
}
/**
* Does the keystore type provide useful values for entry creation dates?
* Some keystores return the keystore load time as creation date for all
* entries, this is not considered useful by this class.
*
* @return true if creation dates are useful, false otherwise
*/
public boolean isEntryCreationDateUseful() {
return entryCreationDateUseful;
}
/**
* Does the keystore type support passwords for entries?
*
* @return true if entry passwords are supported, false otherwise
*/
public boolean isEntryPasswordSupported() {
return entryPasswordSupported;
}
/**
* Common filename extensions associated with this type.
*
* @return filename extensions (without leading dot, in lower case), empty
* if not applicable
*/
public Set<String> getFilenameExtensions() {
return filenameExtensions;
}
/**
* Return string representation of keystore type.
*
* @return String representation of a keystore type
*/
@Override
public String toString() {
return prettyName;
}
/**
* Get set of all known keystore filename extensions.
*
* @return
*/
public static Set<String> getKeyStoreFilenameExtensions() {
HashSet<String> exts = new HashSet<String>();
for (KeyStoreType ksType : values()) {
for (String ext : ksType.getFilenameExtensions()) {
exts.add(ext);
}
}
return exts;
}
}

View File

@@ -0,0 +1,817 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* KeyStoreUtil.java
*/
package org.maxkey.crypto.keystore;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.openssl.PEMParser;
import org.joda.time.DateTime;
import org.maxkey.crypto.Base64Utils;
import org.maxkey.crypto.cert.CryptoException;
import org.maxkey.crypto.cert.X509CertUtils;
import org.maxkey.crypto.cert.X509V3CertGen;
import org.springframework.core.io.Resource;
/**
* Provides utility methods for loading/saving keystores. The Bouncy Castle
* provider must be registered before using this class to create or load BKS or
* UBER type keystores.
*/
public final class KeyStoreUtil {
public static final String X509 = "X.509";
/** Map of available keystore types */
private static final HashMap<KeyStoreType, Boolean> AVAILABLE_TYPES = new HashMap<KeyStoreType, Boolean>();
/**
* Private to prevent construction.
*/
private KeyStoreUtil() {
// Nothing to do
}
/**
* Gets the preferred (by us) KeyStore instance for the given keystore type.
*
* @param keyStoreType The keystore type
* @return The keystore
* @throws KeyStoreException No implementation found
*/
private static KeyStore getKeyStoreImpl(KeyStoreType keyStoreType) throws KeyStoreException {
KeyStore keyStore = null;
if (keyStoreType == KeyStoreType.PKCS12) {
// Prefer BC for PKCS #12 for now; the BC and SunJSSE 1.5+ implementations are
// incompatible in how
// they handle empty/missing passwords; BC works consistently with char[0] on
// load and store (does
// not accept nulls), SunJSSE throws division by zero with char[0] on load and
// store, works with
// null on load, does not work with null on store.
// Checked with BC 1.{29,40}, SunJSSE 1.5.0_0{3,4,14}, 1.6.0 (OpenJDK)
try {
keyStore = KeyStore.getInstance(keyStoreType.name(), "BC");
} catch (NoSuchProviderException ex) {
ex.printStackTrace();
}
}
if (keyStore == null) {
try {
keyStore = KeyStore.getInstance(keyStoreType.name());
} catch (KeyStoreException e) {
AVAILABLE_TYPES.put(keyStoreType, Boolean.FALSE);
throw e;
}
}
AVAILABLE_TYPES.put(keyStoreType, Boolean.TRUE);
return keyStore;
}
/**
* Create a new, empty keystore.
*
* @param keyStoreType The keystore type to create
* @return The keystore
* @throws CryptoException Problem encountered creating the keystore
* @throws IOException An I/O error occurred
*/
public static KeyStore createKeyStore(KeyStoreType keyStoreType) throws CryptoException, IOException {
KeyStore keyStore = null;
try {
keyStore = getKeyStoreImpl(keyStoreType);
keyStore.load(null, null);
} catch (GeneralSecurityException ex) {
throw new CryptoException("Could not create " + keyStoreType + " keystore.", ex);
}
return keyStore;
}
/**
* Load keystore entries from PEM reader into a new PKCS #12 keystore. The
* reader is not closed.
*
* @param reader reader to read entries from
* @return new PKCS #12 keystore containing read entries, possibly empty
* @throws CryptoException Problem encountered creating the keystore
* @throws IOException An I/O error occurred
*/
public static KeyStore loadEntries(PEMParser reader, String password) throws CryptoException, IOException {
LinkedHashSet<KeyPair> keyPairs = new LinkedHashSet<KeyPair>();
LinkedHashSet<Certificate> certs = new LinkedHashSet<Certificate>();
KeyStore keyStore = createKeyStore(KeyStoreType.PKCS12);
Object obj;
while ((obj = reader.readObject()) != null) {
if (obj instanceof KeyPair) {
keyPairs.add((KeyPair) obj);
} else if (obj instanceof Certificate) {
certs.add((Certificate) obj);
}
}
// Add key pairs
for (KeyPair keyPair : keyPairs) {
Certificate keyPairCert = null;
for (Iterator<Certificate> it = certs.iterator(); it.hasNext();) {
Certificate cert = it.next();
if (cert.getPublicKey().equals(keyPair.getPublic())) {
keyPairCert = cert;
it.remove();
break;
}
}
if (keyPairCert != null) {
String alias = "keypair";
if (keyPairCert instanceof X509Certificate) {
alias = X509CertUtils.getCertificateAlias((X509Certificate) keyPairCert);
}
KeyStore.PrivateKeyEntry entry = new KeyStore.PrivateKeyEntry(keyPair.getPrivate(),
new Certificate[] { keyPairCert });
KeyStore.PasswordProtection prot = new KeyStore.PasswordProtection(password.toCharArray());
try {
alias = findUnusedAlias(keyStore, alias);
keyStore.setEntry(alias, entry, prot);
} catch (KeyStoreException e) {
throw new CryptoException(e);
}
}
}
// Add remaining certificates as trusted certificate entries
for (Certificate cert : certs) {
String alias = "certificate";
if (cert instanceof X509Certificate) {
alias = X509CertUtils.getCertificateAlias((X509Certificate) cert);
}
KeyStore.TrustedCertificateEntry entry = new KeyStore.TrustedCertificateEntry(cert);
try {
keyStore.setEntry(alias, entry, null);
} catch (KeyStoreException e) {
throw new CryptoException(e);
}
}
return keyStore;
}
/**
* Check if a keystore type is available.
*
* @param keyStoreType the keystore type
* @return true if the keystore type is available, false otherwise
*/
public static boolean isAvailable(KeyStoreType keyStoreType) {
Boolean available;
if ((available = AVAILABLE_TYPES.get(keyStoreType)) != null) {
return available;
}
try {
// Populate AVAILABLE_TYPES
getKeyStoreImpl(keyStoreType);
} catch (KeyStoreException e) {
// Ignore
e.printStackTrace();
}
return AVAILABLE_TYPES.get(keyStoreType);
}
/**
* Get available keystore types.
*
* @return available keystore types
*/
public static KeyStoreType[] getAvailableTypes() {
// TODO: populate only once
KeyStoreType[] known = KeyStoreType.values();
ArrayList<KeyStoreType> available = new ArrayList<KeyStoreType>();
for (KeyStoreType type : known) {
if (isAvailable(type)) {
available.add(type);
}
}
return available.toArray(new KeyStoreType[available.size()]);
}
/**
* Load a Keystore from a file accessed by a password.
*
* @param keyStoreType The type of the keystore to open
* @param fKeyStore File to load keystore from
* @param cKeyStorePassword Password of the keystore
* @return The keystore
* @throws CryptoException Problem encountered loading the keystore
* @throws FileNotFoundException If the keystore file does not exist, is a
* directory rather than a regular file, or for
* some other reason cannot be opened for reading
*/
public static KeyStore loadKeyStore(
File fKeyStore, char[] cKeyStorePassword, KeyStoreType keyStoreType)
throws CryptoException, FileNotFoundException {
KeyStore keyStore = null;
try {
keyStore = getKeyStoreImpl(keyStoreType);
} catch (KeyStoreException ex) {
throw new CryptoException("Could not create " + keyStoreType + " keystore.", ex);
}
FileInputStream fis = new FileInputStream(fKeyStore);
try {
keyStore.load(fis, cKeyStorePassword);
} catch (GeneralSecurityException ex) {
throw new CryptoException("Could not load keystore as type ''" + keyStoreType + "''.", ex);
} catch (FileNotFoundException ex) {
throw ex;
} catch (IOException ex) {
throw new CryptoException("Could not load keystore as type ''" + keyStoreType + "''.", ex);
} finally {
try {
fis.close();
} catch (IOException ex) {
// Ignore
ex.printStackTrace();
}
}
return keyStore;
}
public static KeyStore loadKeyStore(
Resource keystoreFile, char[] cKeyStorePassword, KeyStoreType keyStoreType)
throws CryptoException, IOException {
KeyStore keyStore = null;
try {
keyStore = getKeyStoreImpl(keyStoreType);
} catch (KeyStoreException ex) {
throw new CryptoException("Could not create " + keyStoreType + " keystore.", ex);
}
InputStream fis = keystoreFile.getInputStream();
try {
keyStore.load(fis, cKeyStorePassword);
} catch (GeneralSecurityException ex) {
throw new CryptoException("Could not load keystore as type ''" + keyStoreType + "''.", ex);
} catch (FileNotFoundException ex) {
throw ex;
} catch (IOException ex) {
throw new CryptoException("Could not load keystore as type ''" + keyStoreType + "''.", ex);
} finally {
try {
fis.close();
} catch (IOException ex) {
// Ignore
ex.printStackTrace();
}
}
return keyStore;
}
public static KeyStore loadKeyStore(String keyStoreB64Encoded, char[] cKeyStorePassword,
KeyStoreType keyStoreType) {
KeyStore keyStore;
try {
//
keyStore = KeyStore.getInstance(keyStoreType.name());
byte[] keyStoreB64 = Base64.decodeBase64(keyStoreB64Encoded.getBytes());
ByteArrayInputStream keyStoreBAIS = new ByteArrayInputStream(keyStoreB64);
keyStore.load(keyStoreBAIS, cKeyStorePassword);
return keyStore;
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static String keyStore2Base64(KeyStore keyStore, String password) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
keyStore.store(stream, password.toCharArray());
byte[] keyStoreByte = stream.toByteArray();
String keyStoreBase64 = Base64Utils.encodeBase64(keyStoreByte);
return keyStoreBase64;
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static KeyStore base642KeyStore(String keyStoreBase64, String password) {
byte[] keyStoreByte = Base64Utils.decoderBase64(keyStoreBase64);
return bytes2KeyStore(keyStoreByte, "JKS", password);
}
/**
* Load a PKCS #11 keystore accessed by a password.
*
* @param sPkcs11Provider The name of the PKCS #11 provider
* @param cKeyStorePassword Password of the keystore
* @return The keystore
* @throws CryptoException Problem encountered loading the keystore
*/
public static KeyStore loadKeyStore(String sPkcs11Provider, char[] cKeyStorePassword) throws CryptoException {
KeyStore keyStore = null;
try {
if (Security.getProvider(sPkcs11Provider) == null) {
throw new CryptoException("The ''" + sPkcs11Provider + "'' provider is not present.");
}
keyStore = KeyStore.getInstance(KeyStoreType.PKCS11.name(), sPkcs11Provider);
} catch (GeneralSecurityException ex) {
throw new CryptoException("Could not create " + KeyStoreType.PKCS11 + " keystore.", ex);
}
try {
keyStore.load(null, cKeyStorePassword);
} catch (Exception ex) {
throw new CryptoException("Could not load keystore as type ''" + KeyStoreType.PKCS11 + "''.", ex);
}
return keyStore;
}
/** */
/**
* <p>
* get a Certificate from keyStore
* </p>
*
* @param keyStore
* @param alias Certificate alias name
* @return
* @throws Exception
*/
public static Certificate getCertificate(KeyStore keyStore, String alias) {
Certificate certificate = null;
try {
certificate = keyStore.getCertificate(alias);
} catch (KeyStoreException e) {
e.printStackTrace();
}
return certificate;
}
/** */
/**
* <p>
* 根据密钥库获得私<E5BE97>?
* </p>
*
* @param keyStorePath 密钥库存储路<E582A8>?
* @param alias 密钥库别<E5BA93>?
* @param password 密钥库密<E5BA93>?
* @return
* @throws Exception
*/
public static PrivateKey getPrivateKey(KeyStore keyStore, String alias, String password) throws Exception {
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
return privateKey;
}
/** */
/**
* <p>
* 根据证书获得公钥
* </p>
*
* @return
* @throws Exception
*/
public static PublicKey getPublicKey(Certificate certificate) throws Exception {
PublicKey publicKey = certificate.getPublicKey();
return publicKey;
}
/** */
/**
* <p>
* 获得证书
* </p>
*
* @param certificatePath 证书存储路径
* @return
* @throws Exception
*/
public static Certificate loadCertificateFromFile(String certificatePath) throws Exception {
CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
FileInputStream in = new FileInputStream(certificatePath);
Certificate certificate = certificateFactory.generateCertificate(in);
in.close();
return certificate;
}
/** */
/**
* <p>
* 根据密钥库获得证<E5BE97>?
* </p>
*
* @param keyStorePath 密钥库存储路<E582A8>?
* @param alias 密钥库别<E5BA93>?
* @param password 密钥库密<E5BA93>?
* @return
* @throws Exception
*/
public static Certificate getCertificate(KeyStore keyStore, String alias, String password) throws Exception {
Certificate certificate = keyStore.getCertificate(alias);
return certificate;
}
/**
* import X509Certificate trustCert to keyStore
*
* @param keyStore
* @param trustCert
* @return KeyStore
*/
public static KeyStore importTrustCertificate(KeyStore keyStore, X509Certificate trustCert) {
String sMatchAlias;
try {
sMatchAlias = X509CertUtils.matchCertificate(keyStore, trustCert);
System.out.println("sMatchAlias : " + sMatchAlias);
if (sMatchAlias != null) {
System.out.println("The certificate already exists in the Keystore under alias ''" + sMatchAlias
+ "''.\nDo you still want to import it?");
} else {
KeyStore[] keyStores = { keyStore };
if (X509CertUtils.establishTrust(keyStores, trustCert) == null) {
System.out.println(
"Could not establish a trust path for the certficate.\nThe certficate information will now be displayed after\nwhich you may confirm whether or not you trust the\ncertificate.");
}
String sCertAlias = X509CertUtils.getCertificateAlias(trustCert).toLowerCase();
// Delete old entry first
if (keyStore.containsAlias(sCertAlias)) {
keyStore.deleteEntry(sCertAlias);
}
// Import the trusted certificate
keyStore.setCertificateEntry(sCertAlias, trustCert);
return keyStore;
}
} catch (CryptoException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
return null;
}
/**
* import X509Certificate trustCert to keyStore
*
* @param keyStore
* @param trustCert
* @return KeyStore
*/
public static KeyStore importTrustCertificate(KeyStore keyStore, X509Certificate trustCert, String sCertAlias) {
String sMatchAlias;
try {
sMatchAlias = X509CertUtils.matchCertificate(keyStore, trustCert);
System.out.println("sMatchAlias : " + sMatchAlias);
if (sMatchAlias != null) {
System.out.println("The certificate already exists in the Keystore under alias ''" + sMatchAlias
+ "''.\nDo you still want to import it?");
} else {
KeyStore[] keyStores = { keyStore };
if (X509CertUtils.establishTrust(keyStores, trustCert) == null) {
System.out.println(
"Could not establish a trust path for the certficate.\nThe certficate information will now be displayed after\nwhich you may confirm whether or not you trust the\ncertificate.");
}
// Delete old entry first
if (keyStore.containsAlias(sCertAlias)) {
keyStore.deleteEntry(sCertAlias);
}
// Import the trusted certificate
keyStore.setCertificateEntry(sCertAlias, trustCert);
return keyStore;
}
} catch (CryptoException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
return null;
}
/**
* Save a keystore to a file protected by a password.
*
* @param keyStore The keystore
* @param fKeyStoreFile The file to save the keystore to
* @param cKeyStorePassword The password to protect the keystore with
* @return the saved keystore ready for further use
* @throws CryptoException Problem encountered saving the keystore
* @throws FileNotFoundException If the keystore file exists but is a directory
* rather than a regular file, does not exist but
* cannot be created, or cannot be opened for any
* other reason
* @throws IOException An I/O error occurred
*/
public static KeyStore saveKeyStore(KeyStore keyStore, File fKeyStoreFile, char[] cKeyStorePassword)
throws CryptoException, IOException {
FileOutputStream fos = new FileOutputStream(fKeyStoreFile);
try {
keyStore.store(fos, cKeyStorePassword);
} catch (IOException ex) {
throw new CryptoException("Could not save keystore.", ex);
} catch (GeneralSecurityException ex) {
throw new CryptoException("Could not save keystore.", ex);
} finally {
fos.close();
}
// As of GNU classpath 0.92, we need to reload GKR keystores after storing them,
// otherwise
// "masked envelope" IllegalStateExceptions occur when trying to access things
// in the stored keystore
// again.
if (KeyStoreType.valueOf(keyStore.getType()) == KeyStoreType.GKR) {
keyStore = loadKeyStore(fKeyStoreFile, cKeyStorePassword, KeyStoreType.GKR);
}
return keyStore;
}
/**
* Find an unused alias in the keystore based on the given alias.
*
* @param keyStore the keystore
* @param alias the alias
* @return alias that is not in use in the keystore
* @throws KeyStoreException
*/
public static String findUnusedAlias(KeyStore keyStore, String alias) throws KeyStoreException {
if (keyStore.containsAlias(alias)) {
int i = 1;
while (true) {
String nextAlias = alias + " (" + i + ")";
if (!keyStore.containsAlias(nextAlias)) {
alias = nextAlias;
break;
}
}
}
return alias;
}
public static KeyStore clone(KeyStore keyStore, String password) {
try {
KeyStore cloneKeyStore = KeyStore.getInstance(keyStore.getType());
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
keyStore.store(byteArrayOutputStream, password.toCharArray());
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
cloneKeyStore.load(byteArrayInputStream, password.toCharArray());
byteArrayInputStream.close();
byteArrayOutputStream.close();
return cloneKeyStore;
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static byte[] keyStore2Bytes(KeyStore keyStore, String password) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
keyStore.store(stream, password.toCharArray());
return stream.toByteArray();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static KeyStore bytes2KeyStore(byte[] keyStoreByte, String keyStoreType, String password) {
try {
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(keyStoreByte);
keyStore.load(byteArrayInputStream, password.toCharArray());
return keyStore;
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static KeyStore setKeyEntry(KeyStore keyStore, String keyEntry, KeyPair keyPair, Certificate certificate,
String password) throws KeyStoreException {
Certificate[] certChain = new Certificate[1];
certChain[0] = certificate;
keyStore.setKeyEntry(keyEntry, (Key) keyPair.getPrivate(), password.toCharArray(), certChain);
return keyStore;
}
public static void main(String[] args) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyPair keyPair = X509V3CertGen.genRSAKeyPair();
String issuer = "CN=connsec.com,O=connsec,L=SH,ST=SH,C=CN";
Date startDate = DateTime.now().toDate();
Date endDate = DateTime.now().plusMonths(10).toDate();
System.out.println("Private : " + keyPair.getPrivate().toString());
System.out.println("Public : " + keyPair.getPublic().toString());
X509Certificate cert = X509V3CertGen.genV3Certificate(issuer, issuer, startDate, endDate, keyPair);
KeyStore keyStore = KeyStoreUtil.createKeyStore(KeyStoreType.JKS);
keyStore = KeyStoreUtil.setKeyEntry(keyStore, "connsec.com", keyPair, cert, "password");
KeyStoreUtil.saveKeyStore(keyStore, new File("c:\\mykeystore"), "password".toCharArray());
keyStore = KeyStoreUtil.loadKeyStore(new File("c:\\mykeystore"), "password".toCharArray(), KeyStoreType.JKS);
System.out.println(KeyStoreUtil.getPrivateKey(keyStore, "connsec.com", "password"));
Certificate certificate = KeyStoreUtil.getCertificate(keyStore, "connsec.com");
System.out.println(KeyStoreUtil.getPublicKey(certificate));
}
/**
* @param args
*
* public static void main(String[] args) {
*
* // new //
* ByteArrayInputStream(Base64.decodeBase64(b64EncodedKeystore.getBytes()))
*
* try { // load a keyStore File file = new
* File("C:\\cert\\idp-keystore.jks"); String keystorePassword =
* "secret"; KeyStore ks = KeyStoreUtil.loadKeyStore(file,
* keystorePassword.toCharArray(), KeyStoreType.JKS);
*
* String b64 = KeyStoreUtil.keyStore2Base64(ks,keystorePassword);
* System.out.println(b64); Enumeration<String> temp = ks.aliases();
* int i = 0; while (temp.hasMoreElements()) {
* System.out.println("KeyStore alias name " + (i++) + " : " +
* temp.nextElement()); }
*
* System.out.println("=================================="); // load
* X509Certificate
*
* // one from pem file Reader reader =new FileReader(new
* File("C:\\cert\\onelogin.pem")); X509Certificate certPem =
* X509CertUtils.loadCertFromReader(reader);
*
* System.out.println("====loadCertificateFromPEMReader:"+certPem.getIssuerDN());
*
* // two from bin file File fileCert = new
* File("C:\\cert\\clientCert.cert"); InputStream isCert = new
* FileInputStream(fileCert); X509Certificate trustCert =
* X509CertUtils.loadCertFromInputStream(isCert);
*
* ks = KeyStoreUtil.importTrustCertificate(ks, trustCert);
*
* System.out
* .println("generatePEMEncoded==================================");
* System.out.println(X509CertUtils.generatePEMEncoded(trustCert));
*
* // output keystore to file KeyStoreUtil.saveKeyStore(ks, new
* File( "C:\\cert\\ClientRegistrarKeyStore12.jks"),
* keystorePassword.toCharArray());
*
* String pemString ="-----BEGIN CERTIFICATE-----"+'\n'; pemString
* +=
* "MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJVUzET"+'\n';
* pemString +=
* "MBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREwDwYD"+'\n';
* pemString +=
* "VQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbTAeFw0xMjEx"+'\n';
* pemString +=
* "MDEwNzUzMTJaFw0xNzExMDEwNzUzMTJaMGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQI"+'\n';
* pemString +=
* "DApDYWxpZm9ybmlhMRUwEwYDVQQHDAxTYW50YSBNb25pY2ExETAPBgNVBAoMCE9u"+'\n';
* pemString +=
* "ZUxvZ2luMRkwFwYDVQQDDBBhcHAub25lbG9naW4uY29tMIIBIjANBgkqhkiG9w0B"+'\n';
* pemString +=
* "AQEFAAOCAQ8AMIIBCgKCAQEAsVV3NROfDQBtSmsyZjdHKre1BMzmnjdyM5vViZV+"+'\n';
* pemString +=
* "OMjLU/aVejupyeNi6i6fqgBzU8a6vz3bXBnL4I8CAZYuRKxz57O2iTMTHLs6cAIT"+'\n';
* pemString +=
* "FTXSfSn/3gxgaOTNfvFXtwSD5yMaxAZckhHCTqVQgUgLLV+JApTSnW22NFadJ8aM"+'\n';
* pemString +=
* "hbajNCbpgIW0CFeiSlbojHzpeZewi8cTgjPDBbxwOeR8VUC6bMWsseqEyxUuHH9E"+'\n';
* pemString +=
* "TmO2pd9m5EKFpqZWlxGqa9qc6e89kpEhbIRpRjPWqSIjeDrsJllAmglsfD5MpnBq"+'\n';
* pemString +=
* "bHXx4BK9cziv6TWMyF0MZ+CnfBWl5JCJaWBFQCs5bG0m8QIDAQABo4HUMIHRMAwG"+'\n';
* pemString +=
* "A1UdEwEB/wQCMAAwHQYDVR0OBBYEFG6SGHTIayKeDRRGEkIdVBeRwjcFMIGRBgNV"+'\n';
* pemString +=
* "HSMEgYkwgYaAFG6SGHTIayKeDRRGEkIdVBeRwjcFoWukaTBnMQswCQYDVQQGEwJV"+'\n';
* pemString +=
* "UzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UEBwwMU2FudGEgTW9uaWNhMREw"+'\n';
* pemString +=
* "DwYDVQQKDAhPbmVMb2dpbjEZMBcGA1UEAwwQYXBwLm9uZWxvZ2luLmNvbYIBATAO"+'\n';
* pemString +=
* "BgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADggEBAGkBjaIhHusWRmY0O16+"+'\n';
* pemString +=
* "WoKC7l5Re2C+bz+tyuSLlDcuHniAsyhbYG8xvEJSOnxpeFbS/a4ko80wSsd+sUXJ"+'\n';
* pemString +=
* "FR3Z40W0JNT6ELn5Tf51b+cbm3erucMxKIDiMsQBcO/nHHBQs25kTXeKBjLnR/9u"+'\n';
* pemString +=
* "i3+naVemnRb1cvffenAPpm12yKqWWcKgN19mE2vdrw0y/GoirFFtO/STdkDPKuYu"+'\n';
* pemString +=
* "6wubRBeURNzqims0xe4/vPFE7iN50bjgKcuPn6LMaIDrLJVkwMC09MNsr0Dgmqgt"+'\n';
* pemString +=
* "hBdnEqXkhdE8F/VneHn5xLSfExC662OaU6jqDASBvN15mrLGaQ+Ou9qOsCFi7wg6"+'\n';
* pemString += "8QI="+'\n'; pemString += "-----END
* CERTIFICATE-----"+'\n';
*
* System.out.println(pemString); X509Certificate x509Certificate =
* X509CertUtils.loadCertFromPEM(pemString);
* System.out.println(x509Certificate.getIssuerDN()); } catch
* (IOException e) { e.printStackTrace(); } catch (KeyStoreException
* e) { e.printStackTrace(); } catch (Exception e) {
* e.printStackTrace(); }
*
* }
*/
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.password;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Digester {
private final String algorithm;
private int iterations;
/**
* Create a new Digester.
* @param algorithm the digest algorithm; for example, "SHA-1" or "SHA-256".
* @param iterations the number of times to apply the digest algorithm to the input
*/
Digester(String algorithm, int iterations) {
// eagerly validate the algorithm
createDigest(algorithm);
this.algorithm = algorithm;
setIterations(iterations);
}
public byte[] digest(byte[] value) {
MessageDigest messageDigest = createDigest(algorithm);
for (int i = 0; i < iterations; i++) {
value = messageDigest.digest(value);
}
return value;
}
void setIterations(int iterations) {
if (iterations <= 0) {
throw new IllegalArgumentException("Iterations value must be greater than zero");
}
this.iterations = iterations;
}
private static MessageDigest createDigest(String algorithm) {
try {
return MessageDigest.getInstance(algorithm);
}
catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("No such hashing algorithm", e);
}
}
}

View File

@@ -0,0 +1,228 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.password;
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.security.crypto.codec.Utf8;
import org.springframework.security.crypto.keygen.BytesKeyGenerator;
import org.springframework.security.crypto.keygen.KeyGenerators;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.security.MessageDigest;
import java.util.Base64;
/**
* This {@link PasswordEncoder} is provided for legacy purposes only and is not considered
* secure.
*
* A version of {@link PasswordEncoder} which supports Ldap SHA and SSHA (salted-SHA)
* encodings. The values are base-64 encoded and have the label "{SHA}" (or "{SSHA}")
* prepended to the encoded hash. These can be made lower-case in the encoded password, if
* required, by setting the <tt>forceLowerCasePrefix</tt> property to true.
*
* Also supports plain text passwords, so can safely be used in cases when both encoded
* and non-encoded passwords are in use or when a null implementation is required.
*
* @author Luke Taylor
* deprecated Digest based password encoding is not considered secure. Instead use an
* adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
* SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports
* password upgrades. There are no plans to remove this support. It is deprecated to indicate
* that this is a legacy implementation and using it is considered insecure.
*/
public class LdapShaPasswordEncoder implements PasswordEncoder {
// ~ Static fields/initializers
// =====================================================================================
/** The number of bytes in a SHA hash */
private static final int SHA_LENGTH = 20;
private static final String SSHA_PREFIX = "{SSHA}";
private static final String SSHA_PREFIX_LC = SSHA_PREFIX.toLowerCase();
private static final String SHA_PREFIX = "{SHA}";
private static final String SHA_PREFIX_LC = SHA_PREFIX.toLowerCase();
// ~ Instance fields
// ================================================================================================
private BytesKeyGenerator saltGenerator;
private boolean forceLowerCasePrefix;
// ~ Constructors
// ===================================================================================================
public LdapShaPasswordEncoder() {
this(KeyGenerators.secureRandom());
}
public LdapShaPasswordEncoder(BytesKeyGenerator saltGenerator) {
if (saltGenerator == null) {
throw new IllegalArgumentException("saltGenerator cannot be null");
}
this.saltGenerator = saltGenerator;
}
// ~ Methods
// ========================================================================================================
private byte[] combineHashAndSalt(byte[] hash, byte[] salt) {
if (salt == null) {
return hash;
}
byte[] hashAndSalt = new byte[hash.length + salt.length];
System.arraycopy(hash, 0, hashAndSalt, 0, hash.length);
System.arraycopy(salt, 0, hashAndSalt, hash.length, salt.length);
return hashAndSalt;
}
/**
* Calculates the hash of password (and salt bytes, if supplied) and returns a base64
* encoded concatenation of the hash and salt, prefixed with {SHA} (or {SSHA} if salt
* was used).
*
* @param rawPass the password to be encoded.
*
* @return the encoded password in the specified format
*
*/
public String encode(CharSequence rawPass) {
byte[] salt = this.saltGenerator.generateKey();
return encode(rawPass, salt);
}
private String encode(CharSequence rawPassword, byte[] salt) {
MessageDigest sha;
try {
sha = MessageDigest.getInstance("SHA");
sha.update(Utf8.encode(rawPassword));
}
catch (java.security.NoSuchAlgorithmException e) {
throw new IllegalStateException("No SHA implementation available!");
}
if (salt != null) {
sha.update(salt);
}
byte[] hash = combineHashAndSalt(sha.digest(), salt);
String prefix;
if (salt == null || salt.length == 0) {
prefix = forceLowerCasePrefix ? SHA_PREFIX_LC : SHA_PREFIX;
}
else {
prefix = forceLowerCasePrefix ? SSHA_PREFIX_LC : SSHA_PREFIX;
}
return prefix + Utf8.decode(Base64.getEncoder().encode(hash));
}
private byte[] extractSalt(String encPass) {
String encPassNoLabel = encPass.substring(6);
byte[] hashAndSalt = Base64.getDecoder().decode(encPassNoLabel.getBytes());
int saltLength = hashAndSalt.length - SHA_LENGTH;
byte[] salt = new byte[saltLength];
System.arraycopy(hashAndSalt, SHA_LENGTH, salt, 0, saltLength);
return salt;
}
/**
* Checks the validity of an unencoded password against an encoded one in the form
* "{SSHA}sQuQF8vj8Eg2Y1hPdh3bkQhCKQBgjhQI".
*
* @param rawPassword unencoded password to be verified.
* @param encodedPassword the actual SSHA or SHA encoded password
*
* @return true if they match (independent of the case of the prefix).
*/
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return matches(rawPassword == null ? null : rawPassword.toString(), encodedPassword);
}
private boolean matches(String rawPassword, String encodedPassword) {
String prefix = extractPrefix(encodedPassword);
if (prefix == null) {
return PasswordEncoderUtils.equals(encodedPassword, rawPassword);
}
byte[] salt;
if (prefix.equals(SSHA_PREFIX) || prefix.equals(SSHA_PREFIX_LC)) {
salt = extractSalt(encodedPassword);
}
else if (!prefix.equals(SHA_PREFIX) && !prefix.equals(SHA_PREFIX_LC)) {
throw new IllegalArgumentException("Unsupported password prefix '" + prefix
+ "'");
}
else {
// Standard SHA
salt = null;
}
int startOfHash = prefix.length();
String encodedRawPass = encode(rawPassword, salt).substring(startOfHash);
return PasswordEncoderUtils
.equals(encodedRawPass, encodedPassword.substring(startOfHash));
}
/**
* Returns the hash prefix or null if there isn't one.
*/
private String extractPrefix(String encPass) {
if (!encPass.startsWith("{")) {
return null;
}
int secondBrace = encPass.lastIndexOf('}');
if (secondBrace < 0) {
throw new IllegalArgumentException(
"Couldn't find closing brace for SHA prefix");
}
return encPass.substring(0, secondBrace + 1);
}
public void setForceLowerCasePrefix(boolean forceLowerCasePrefix) {
this.forceLowerCasePrefix = forceLowerCasePrefix;
}
}

View File

@@ -0,0 +1,201 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.password;
/*
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Implementation of the MD4 message digest derived from the RSA Data Security, Inc, MD4
* Message-Digest Algorithm.
*
* @author Alan Stewart
*/
class Md4 {
private static final int BLOCK_SIZE = 64;
private static final int HASH_SIZE = 16;
private final byte[] buffer = new byte[BLOCK_SIZE];
private int bufferOffset;
private long byteCount;
private final int[] state = new int[4];
private final int[] tmp = new int[16];
Md4() {
reset();
}
public void reset() {
bufferOffset = 0;
byteCount = 0;
state[0] = 0x67452301;
state[1] = 0xEFCDAB89;
state[2] = 0x98BADCFE;
state[3] = 0x10325476;
}
public byte[] digest() {
byte[] resBuf = new byte[HASH_SIZE];
digest(resBuf, 0, HASH_SIZE);
return resBuf;
}
private void digest(byte[] buffer, int off) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
buffer[off + (i * 4 + j)] = (byte) (state[i] >>> (8 * j));
}
}
}
private void digest(byte[] buffer, int offset, int len) {
this.buffer[this.bufferOffset++] = (byte) 0x80;
int lenOfBitLen = 8;
int C = BLOCK_SIZE - lenOfBitLen;
if (this.bufferOffset > C) {
while (this.bufferOffset < BLOCK_SIZE) {
this.buffer[this.bufferOffset++] = (byte) 0x00;
}
update(this.buffer, 0);
this.bufferOffset = 0;
}
while (this.bufferOffset < C) {
this.buffer[this.bufferOffset++] = (byte) 0x00;
}
long bitCount = byteCount * 8;
for (int i = 0; i < 64; i += 8) {
this.buffer[this.bufferOffset++] = (byte) (bitCount >>> (i));
}
update(this.buffer, 0);
digest(buffer, offset);
}
public void update(byte[] input, int offset, int length) {
byteCount += length;
int todo;
while (length >= (todo = BLOCK_SIZE - this.bufferOffset)) {
System.arraycopy(input, offset, this.buffer, this.bufferOffset, todo);
update(this.buffer, 0);
length -= todo;
offset += todo;
this.bufferOffset = 0;
}
System.arraycopy(input, offset, this.buffer, this.bufferOffset, length);
bufferOffset += length;
}
private void update(byte[] block, int offset) {
for (int i = 0; i < 16; i++) {
tmp[i] = (block[offset++] & 0xFF) | (block[offset++] & 0xFF) << 8
| (block[offset++] & 0xFF) << 16 | (block[offset++] & 0xFF) << 24;
}
int A = state[0];
int B = state[1];
int C = state[2];
int D = state[3];
A = FF(A, B, C, D, tmp[0], 3);
D = FF(D, A, B, C, tmp[1], 7);
C = FF(C, D, A, B, tmp[2], 11);
B = FF(B, C, D, A, tmp[3], 19);
A = FF(A, B, C, D, tmp[4], 3);
D = FF(D, A, B, C, tmp[5], 7);
C = FF(C, D, A, B, tmp[6], 11);
B = FF(B, C, D, A, tmp[7], 19);
A = FF(A, B, C, D, tmp[8], 3);
D = FF(D, A, B, C, tmp[9], 7);
C = FF(C, D, A, B, tmp[10], 11);
B = FF(B, C, D, A, tmp[11], 19);
A = FF(A, B, C, D, tmp[12], 3);
D = FF(D, A, B, C, tmp[13], 7);
C = FF(C, D, A, B, tmp[14], 11);
B = FF(B, C, D, A, tmp[15], 19);
A = GG(A, B, C, D, tmp[0], 3);
D = GG(D, A, B, C, tmp[4], 5);
C = GG(C, D, A, B, tmp[8], 9);
B = GG(B, C, D, A, tmp[12], 13);
A = GG(A, B, C, D, tmp[1], 3);
D = GG(D, A, B, C, tmp[5], 5);
C = GG(C, D, A, B, tmp[9], 9);
B = GG(B, C, D, A, tmp[13], 13);
A = GG(A, B, C, D, tmp[2], 3);
D = GG(D, A, B, C, tmp[6], 5);
C = GG(C, D, A, B, tmp[10], 9);
B = GG(B, C, D, A, tmp[14], 13);
A = GG(A, B, C, D, tmp[3], 3);
D = GG(D, A, B, C, tmp[7], 5);
C = GG(C, D, A, B, tmp[11], 9);
B = GG(B, C, D, A, tmp[15], 13);
A = HH(A, B, C, D, tmp[0], 3);
D = HH(D, A, B, C, tmp[8], 9);
C = HH(C, D, A, B, tmp[4], 11);
B = HH(B, C, D, A, tmp[12], 15);
A = HH(A, B, C, D, tmp[2], 3);
D = HH(D, A, B, C, tmp[10], 9);
C = HH(C, D, A, B, tmp[6], 11);
B = HH(B, C, D, A, tmp[14], 15);
A = HH(A, B, C, D, tmp[1], 3);
D = HH(D, A, B, C, tmp[9], 9);
C = HH(C, D, A, B, tmp[5], 11);
B = HH(B, C, D, A, tmp[13], 15);
A = HH(A, B, C, D, tmp[3], 3);
D = HH(D, A, B, C, tmp[11], 9);
C = HH(C, D, A, B, tmp[7], 11);
B = HH(B, C, D, A, tmp[15], 15);
state[0] += A;
state[1] += B;
state[2] += C;
state[3] += D;
}
private int FF(int a, int b, int c, int d, int x, int s) {
int t = a + ((b & c) | (~b & d)) + x;
return t << s | t >>> (32 - s);
}
private int GG(int a, int b, int c, int d, int x, int s) {
int t = a + ((b & (c | d)) | (c & d)) + x + 0x5A827999;
return t << s | t >>> (32 - s);
}
private int HH(int a, int b, int c, int d, int x, int s) {
int t = a + (b ^ c ^ d) + x + 0x6ED9EBA1;
return t << s | t >>> (32 - s);
}
}

View File

@@ -0,0 +1,171 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.password;
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.security.crypto.codec.Hex;
import org.springframework.security.crypto.codec.Utf8;
import org.springframework.security.crypto.keygen.Base64StringKeyGenerator;
import org.springframework.security.crypto.keygen.StringKeyGenerator;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.Base64;
/**
* This {@link PasswordEncoder} is provided for legacy purposes only and is not considered secure.
*
* Encodes passwords using MD4. The general format of the password is:
*
* <pre>
* s = salt == null ? "" : "{" + salt + "}"
* s + md4(password + s)
* </pre>
*
* Such that "salt" is the salt, md4 is the digest method, and password is the actual
* password. For example with a password of "password", and a salt of
* "thisissalt":
*
* <pre>
* String s = salt == null ? "" : "{" + salt + "}";
* s + md4(password + s)
* "{thisissalt}" + md4(password + "{thisissalt}")
* "{thisissalt}6cc7924dad12ade79dfb99e424f25260"
* </pre>
*
* If the salt does not exist, then omit "{salt}" like this:
*
* <pre>
* md4(password)
* </pre>
*
* If the salt is an empty String, then only use "{}" like this:
*
* <pre>
* "{}" + md4(password + "{}")
* </pre>
*
* The format is intended to work with the Md4PasswordEncoder that was found in the
* Spring Security core module. However, the passwords will need to be migrated to include
* any salt with the password since this API provides Salt internally vs making it the
* responsibility of the user. To migrate passwords from the SaltSource use the following:
*
* <pre>
* String salt = saltSource.getSalt(user);
* String s = salt == null ? null : "{" + salt + "}";
* String migratedPassword = s + user.getPassword();
* </pre>
*
* @author Ray Krueger
* @author Luke Taylor
* @author Rob winch
* @since 5.0
* deprecated Digest based password encoding is not considered secure. Instead use an
* adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
* SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports
* password upgrades. There are no plans to remove this support. It is deprecated to indicate
* that this is a legacy implementation and using it is considered insecure.
*/
public class Md4PasswordEncoder implements PasswordEncoder {
private static final String PREFIX = "{";
private static final String SUFFIX = "}";
private StringKeyGenerator saltGenerator = new Base64StringKeyGenerator();
private boolean encodeHashAsBase64;
public void setEncodeHashAsBase64(boolean encodeHashAsBase64) {
this.encodeHashAsBase64 = encodeHashAsBase64;
}
/**
* Encodes the rawPass using a MessageDigest. If a salt is specified it will be merged
* with the password before encoding.
*
* @param rawPassword The plain text password
* @return Hex string of password digest (or base64 encoded string if
* encodeHashAsBase64 is enabled.
*/
public String encode(CharSequence rawPassword) {
String salt = PREFIX + this.saltGenerator.generateKey() + SUFFIX;
return digest(salt, rawPassword);
}
private String digest(String salt, CharSequence rawPassword) {
if (rawPassword == null) {
rawPassword = "";
}
String saltedPassword = rawPassword + salt;
byte[] saltedPasswordBytes = Utf8.encode(saltedPassword);
Md4 md4 = new Md4();
md4.update(saltedPasswordBytes, 0, saltedPasswordBytes.length);
byte[] digest = md4.digest();
String encoded = encode(digest);
return salt + encoded;
}
private String encode(byte[] digest) {
if (this.encodeHashAsBase64) {
return Utf8.decode(Base64.getEncoder().encode(digest));
}
else {
return new String(Hex.encode(digest));
}
}
/**
* Takes a previously encoded password and compares it with a rawpassword after mixing
* in the salt and encoding that value
*
* @param rawPassword plain text password
* @param encodedPassword previously encoded password
* @return true or false
*/
public boolean matches(CharSequence rawPassword, String encodedPassword) {
String salt = extractSalt(encodedPassword);
String rawPasswordEncoded = digest(salt, rawPassword);
return PasswordEncoderUtils.equals(encodedPassword.toString(), rawPasswordEncoded);
}
private String extractSalt(String prefixEncodedPassword) {
int start = prefixEncodedPassword.indexOf(PREFIX);
if (start != 0) {
return "";
}
int end = prefixEncodedPassword.indexOf(SUFFIX, start);
if (end < 0) {
return "";
}
return prefixEncodedPassword.substring(start, end + 1);
}
}

View File

@@ -0,0 +1,193 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.password;
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.security.crypto.codec.Hex;
import org.springframework.security.crypto.codec.Utf8;
import org.springframework.security.crypto.keygen.Base64StringKeyGenerator;
import org.springframework.security.crypto.keygen.StringKeyGenerator;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.security.MessageDigest;
import java.util.Base64;
/**
* This {@link PasswordEncoder} is provided for legacy purposes only and is not considered secure.
*
* Encodes passwords using the passed in {@link MessageDigest}.
*
* The general format of the password is:
*
* <pre>
* s = salt == null ? "" : "{" + salt + "}"
* s + digest(password + s)
* </pre>
*
* Such that "salt" is the salt, digest is the digest method, and password is the actual
* password. For example when using MD5, a password of "password", and a salt of
* "thisissalt":
*
* <pre>
* String s = salt == null ? "" : "{" + salt + "}";
* s + md5(password + s)
* "{thisissalt}" + md5(password + "{thisissalt}")
* "{thisissalt}2a4e7104c2780098f50ed5a84bb2323d"
* </pre>
*
* If the salt does not exist, then omit "{salt}" like this:
*
* <pre>
* digest(password)
* </pre>
*
* If the salt is an empty String, then only use "{}" like this:
*
* <pre>
* "{}" + digest(password + "{}")
* </pre>
*
* The format is intended to work with the DigestPasswordEncoder that was found in the
* Spring Security core module. However, the passwords will need to be migrated to include
* any salt with the password since this API provides Salt internally vs making it the
* responsibility of the user. To migrate passwords from the SaltSource use the following:
*
* <pre>
* String salt = saltSource.getSalt(user);
* String s = salt == null ? null : "{" + salt + "}";
* String migratedPassword = s + user.getPassword();
* </pre>
*
* @author Ray Krueger
* @author Luke Taylor
* @author Rob Winch
* @since 5.0
* deprecated Digest based password encoding is not considered secure. Instead use an
* adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
* SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports
* password upgrades. There are no plans to remove this support. It is deprecated to indicate
* that this is a legacy implementation and using it is considered insecure.
*/
public class MessageDigestPasswordEncoder implements PasswordEncoder {
private static final String PREFIX = "{";
private static final String SUFFIX = "}";
private StringKeyGenerator saltGenerator = new Base64StringKeyGenerator();
private boolean encodeHashAsBase64;
private Digester digester;
/**
* The digest algorithm to use Supports the named
* <a href="https://java.sun.com/j2se/1.4.2/docs/guide/security/CryptoSpec.html#AppA">
* Message Digest Algorithms</a> in the Java environment.
*
* @param algorithm
*/
public MessageDigestPasswordEncoder(String algorithm) {
this.digester = new Digester(algorithm, 1);
}
public void setEncodeHashAsBase64(boolean encodeHashAsBase64) {
this.encodeHashAsBase64 = encodeHashAsBase64;
}
/**
* Encodes the rawPass using a MessageDigest. If a salt is specified it will be merged
* with the password before encoding.
*
* @param rawPassword The plain text password
* @return Hex string of password digest (or base64 encoded string if
* encodeHashAsBase64 is enabled.
*/
public String encode(CharSequence rawPassword) {
String salt = PREFIX + this.saltGenerator.generateKey() + SUFFIX;
return digest(salt, rawPassword);
}
private String digest(String salt, CharSequence rawPassword) {
String saltedPassword = rawPassword + salt;
byte[] digest = this.digester.digest(Utf8.encode(saltedPassword));
String encoded = encode(digest);
return salt + encoded;
}
private String encode(byte[] digest) {
if (this.encodeHashAsBase64) {
return Utf8.decode(Base64.getEncoder().encode(digest));
}
else {
return new String(Hex.encode(digest));
}
}
/**
* Takes a previously encoded password and compares it with a rawpassword after mixing
* in the salt and encoding that value
*
* @param rawPassword plain text password
* @param encodedPassword previously encoded password
* @return true or false
*/
public boolean matches(CharSequence rawPassword, String encodedPassword) {
String salt = extractSalt(encodedPassword);
String rawPasswordEncoded = digest(salt, rawPassword);
return PasswordEncoderUtils.equals(encodedPassword.toString(), rawPasswordEncoded);
}
/**
* Sets the number of iterations for which the calculated hash value should be
* "stretched". If this is greater than one, the initial digest is calculated, the
* digest function will be called repeatedly on the result for the additional number
* of iterations.
*
* @param iterations the number of iterations which will be executed on the hashed
* password/salt value. Defaults to 1.
*/
public void setIterations(int iterations) {
this.digester.setIterations(iterations);
}
private String extractSalt(String prefixEncodedPassword) {
int start = prefixEncodedPassword.indexOf(PREFIX);
if (start != 0) {
return "";
}
int end = prefixEncodedPassword.indexOf(SUFFIX, start);
if (end < 0) {
return "";
}
return prefixEncodedPassword.substring(start, end + 1);
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.password;
import org.springframework.security.crypto.password.PasswordEncoder;
/*
* Copyright 2011-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This {@link PasswordEncoder} is provided for legacy and testing purposes only and is
* not considered secure.
*
* A password encoder that does nothing. Useful for testing where working with plain text
* passwords may be preferred.
*
* @author Keith Donald
* deprecated This PasswordEncoder is not secure. Instead use an
* adaptive one way function like BCryptPasswordEncoder, Pbkdf2PasswordEncoder, or
* SCryptPasswordEncoder. Even better use {@link DelegatingPasswordEncoder} which supports
* password upgrades. There are no plans to remove this support. It is deprecated to indicate that
* this is a legacy implementation and using it is considered insecure.
*/
public final class NoOpPasswordEncoder implements PasswordEncoder {
public String encode(CharSequence rawPassword) {
return rawPassword.toString();
}
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return rawPassword.toString().equals(encodedPassword);
}
/**
* Get the singleton {@link NoOpPasswordEncoder}.
*/
public static PasswordEncoder getInstance() {
return INSTANCE;
}
private static final PasswordEncoder INSTANCE = new NoOpPasswordEncoder();
private NoOpPasswordEncoder() {
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.password;
import org.springframework.security.crypto.codec.Utf8;
import java.security.MessageDigest;
/**
* Utility for constant time comparison to prevent against timing attacks.
*
* @author Rob Winch
*/
public class PasswordEncoderUtils {
/**
* Constant time comparison to prevent against timing attacks.
* @param expected
* @param actual
* @return
*/
static boolean equals(String expected, String actual) {
byte[] expectedBytes = bytesUtf8(expected);
byte[] actualBytes = bytesUtf8(actual);
return MessageDigest.isEqual(expectedBytes, actualBytes);
}
private static byte[] bytesUtf8(String s) {
if (s == null) {
return null;
}
return Utf8.encode(s); // need to check if Utf8.encode() runs in constant time (probably not). This may leak length of string.
}
private PasswordEncoderUtils() {
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.password;
import java.util.Random;
/**
* PasswordGen.
* @author Crystal.Sea
*
*
*/
public class PasswordGen {
public static String CHAR_LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
public static String CHAR_UPPERCASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static String CHAR_NUMBERS = "0123456789";
public static String CHAR_SPECIAL = "~@#^()[]*$-+?_&=!%{}/";
public static String CHAR_DEFAULT = CHAR_LOWERCASE + CHAR_NUMBERS + CHAR_UPPERCASE;
private Random random = new Random();
public static int DEFAULT_LENGTH = 8;
private int length;
public PasswordGen() {
length = DEFAULT_LENGTH;
}
public PasswordGen(int length) {
this.length = length;
}
public String gen() {
this.length = DEFAULT_LENGTH;
return gen(length);
}
public String gen(int length) {
this.length = length;
return gen(CHAR_DEFAULT, length);
}
/**
* gen .
* @param lowerCase int
* @param upperCase int
* @param numbers int
* @param special int
* @return
*/
public String gen(int lowerCase, int upperCase, int numbers, int special) {
StringBuffer password = new StringBuffer("");
password.append(gen(CHAR_LOWERCASE, lowerCase));
password.append(gen(CHAR_NUMBERS, numbers));
password.append(gen(CHAR_UPPERCASE, upperCase));
password.append(gen(CHAR_SPECIAL, special));
password.append(gen(CHAR_DEFAULT, length - lowerCase - upperCase - numbers -special));
// random generator String by sequence password
return gen(password.toString(), password.length());
}
/**
* gen.
* @param charString String
* @param length int
* @return
*/
public String gen(final String charString, int length) {
if (length < 1) {
return "";
}
int i = 0;
StringBuffer password = new StringBuffer("");
while (i < length) {
int randomPosition = random.nextInt(charString.length());
// duplicate check
if (password.indexOf(charString.charAt(randomPosition) + "") < 0) {
password.append(charString.charAt(randomPosition));
i++;
}
}
return password.toString();
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.password;
import org.maxkey.crypto.ReciprocalUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* PasswordReciprocal.
* @author Crystal.Sea
*
*/
public class PasswordReciprocal implements PasswordEncoder {
public static PasswordReciprocal passwordReciprocal;
public PasswordReciprocal() {
}
/**
* getInstance.
* @return
*/
public static PasswordReciprocal getInstance() {
if (passwordReciprocal == null) {
passwordReciprocal = new PasswordReciprocal();
}
return passwordReciprocal;
}
public String rawPassword(String username, String password) {
return password + "@" + username;
}
public String encode(CharSequence rawPassword) {
return ReciprocalUtils.encode(rawPassword.toString());
}
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return ReciprocalUtils.encode(rawPassword.toString()).equals(encodedPassword);
}
public String decoder(CharSequence encodedPassword) {
if(encodedPassword == null || encodedPassword.equals("")) {
return "";
}
return ReciprocalUtils.decoder(encodedPassword.toString());
}
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.password;
import org.springframework.security.crypto.codec.Hex;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.maxkey.crypto.*;
public class SM3PasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence rawPassword) {
String cipher = new String(Hex.encode(SM3.encode(rawPassword.toString().getBytes())));
return cipher;
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
String cipher = encode(rawPassword);
return encodedPassword.equals(cipher);
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.password;
import static org.springframework.security.crypto.util.EncodingUtils.concatenate;
import static org.springframework.security.crypto.util.EncodingUtils.subArray;
import java.security.MessageDigest;
import org.springframework.security.crypto.codec.Hex;
import org.springframework.security.crypto.codec.Utf8;
import org.springframework.security.crypto.keygen.BytesKeyGenerator;
import org.springframework.security.crypto.keygen.KeyGenerators;
import org.springframework.security.crypto.password.PasswordEncoder;
public final class StandardPasswordEncoder implements PasswordEncoder {
private final Digester digester;
private final byte[] secret;
private final BytesKeyGenerator saltGenerator;
/**
* Constructs a standard password encoder with no additional secret value.
*/
public StandardPasswordEncoder() {
this("");
}
/**
* Constructs a standard password encoder with a secret value which is also included
* in the password hash.
*
* @param secret the secret key used in the encoding process (should not be shared)
*/
public StandardPasswordEncoder(CharSequence secret) {
this("SHA-256", secret);
}
public String encode(CharSequence rawPassword) {
return encode(rawPassword, saltGenerator.generateKey());
}
public boolean matches(CharSequence rawPassword, String encodedPassword) {
byte[] digested = decode(encodedPassword);
byte[] salt = subArray(digested, 0, saltGenerator.getKeyLength());
return MessageDigest.isEqual(digested, digest(rawPassword, salt));
}
// internal helpers
public StandardPasswordEncoder(String algorithm, CharSequence secret) {
this.digester = new Digester(algorithm, DEFAULT_ITERATIONS);
this.secret = Utf8.encode(secret);
this.saltGenerator = KeyGenerators.secureRandom();
}
private String encode(CharSequence rawPassword, byte[] salt) {
byte[] digest = digest(rawPassword, salt);
return new String(Hex.encode(digest));
}
private byte[] digest(CharSequence rawPassword, byte[] salt) {
byte[] digest = digester.digest(concatenate(salt, secret,
Utf8.encode(rawPassword)));
return concatenate(salt, digest);
}
private byte[] decode(CharSequence encodedPassword) {
return Hex.decode(encodedPassword);
}
private static final int DEFAULT_ITERATIONS = 1024;
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.signature;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import org.maxkey.crypto.Base64Utils;
import org.maxkey.crypto.KeyPairType;
/**
* DSA Digital signature
* default signature algorithm is SHA1withDSA
* default key size is 1024
* DsaSigner support SHA1withDSA
* @author Crystal.Sea
*
*/
public final class DsaSigner implements ISigner {
// <20><><EFBFBD><EFBFBD>ǩ<EFBFBD><C7A9><EFBFBD><EFBFBD>Կ<EFBFBD>
public static final KeyPairType KEY_ALGORITHM = KeyPairType.DSA;
/**
* <20><><EFBFBD><EFBFBD>ǩ<EFBFBD><C7A9> ǩ<><C7A9>/<2F><>֤<EFBFBD>
* */
public static final String SIGNATURE_ALGORITHM = "SHA1withDSA";
public byte[] sign(byte[] dataBytes, byte[] privateKeyByte) throws Exception {
// ȡ<><C8A1>˽Կ
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyByte);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM.name());
// <20><><EFBFBD>˽Կ
PrivateKey signPrivateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// ʵ<><CAB5>Signature
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
// <20><>ʼ<EFBFBD><CABC>Signature
signature.initSign(signPrivateKey);
// <20><><EFBFBD><EFBFBD>
signature.update(dataBytes);
return signature.sign();
}
public String signB64(String data, String privateKey) throws Exception {
byte[] privateKeyByte = Base64Utils.decoder(privateKey);
byte[] dataBytes = data.getBytes();
byte[] signatureBytes=sign(dataBytes,privateKeyByte);
return Base64Utils.encoder(signatureBytes);
}
public boolean verify(byte[] dataBytes, byte[] publicKeyBytes, byte[] signBytes)throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM.name());
// <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>Կ
// <20><>Կ<EFBFBD><D4BF><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
// <20><><EFBFBD><EFBFBD>Կ
PublicKey verifyPublicKey = keyFactory.generatePublic(x509KeySpec);
// ʵ<><CAB5>Signature
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
// <20><>ʼ<EFBFBD><CABC>Signature
signature.initVerify(verifyPublicKey);
// <20><><EFBFBD><EFBFBD>
signature.update(dataBytes);
// <20><>֤
return signature.verify(signBytes);
}
public boolean verifyB64(String data, String publicKey, String sign)throws Exception {
byte[] privateKeyByte = Base64Utils.decoder(publicKey);
byte[] dataBytes = data.getBytes();
byte[] signBytes=Base64Utils.decoder(sign);
// <20><>֤
return verify(dataBytes,privateKeyByte,signBytes);
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.crypto.signature;
/**
* Digital signature
* interface for RSA & DSA
* sign with private key ,then verify use public key
* scenario
* 1. A genKeyPair include private key & public key
* 2. A give public key to B
* 3. A sign a data with private key to signedData
* 4. A send data and signedData to B
* 5. B received data & signedData from A
* 6. B verify data & signedData use public key
*
* @author Crystal.Sea
*
*/
public interface ISigner {
public byte[] sign(byte[] data,byte[] privateKey)throws Exception;
public String signB64(String data,String privateKey)throws Exception;
public boolean verify(byte[] data,byte[] publicKey,byte[] sign)throws Exception;
public boolean verifyB64(String data,String publicKey,String sign)throws Exception;
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.crypto.signature;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import org.maxkey.crypto.Base64Utils;
import org.maxkey.crypto.KeyPairType;
/**
* RSA Digital signature
* default signature algorithm is SHA1withRSA
* default key size is 1024
* RsaSigner support MD5withRSA and MD5withRSA
* @author Crystal.Sea
*
*/
public final class RsaSigner implements ISigner {
public static final KeyPairType KEY_ALGORTHM = KeyPairType.RSA;
public final class RsaAlgorithm {
public static final String MD5withRSA="MD5withRSA";
public static final String SHA1withRSA = "SHA1withRSA";
}
public static final String SIGNATURE_ALGORITHM = RsaAlgorithm.SHA1withRSA;
public byte[] sign(byte[] dataBytes, byte[] privateKeyBytes, String algorithm)throws Exception {
// <20><><EFBFBD><EFBFBD>PKCS8EncodedKeySpec<65><63><EFBFBD><EFBFBD>
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
// ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM.name());
// ȡ˽Կ<CBBD>׶<EFBFBD><D7B6><EFBFBD>
PrivateKey signPrivateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
// <20><>˽Կ<CBBD><D4BF><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD><C7A9>
Signature signature = Signature.getInstance(algorithm);
signature.initSign(signPrivateKey);
signature.update(dataBytes);
return signature.sign();
}
public byte[] sign(byte[] dataBytes, byte[] privateKeyBytes) throws Exception {
return sign(dataBytes,privateKeyBytes,SIGNATURE_ALGORITHM);
}
/**
* sign with BASE64 privateKey use SHA1withRSA Algorithm
*/
public String signB64(String data, String privateKey) throws Exception {
byte[] keyBytes = Base64Utils.decoder(privateKey);
byte[] dataBytes = data.getBytes();
byte[] signature=sign(dataBytes,keyBytes);
return Base64Utils.encoder(signature);
}
public boolean verify(byte[] dataBytes, byte[] publicKeyBytes , byte[] signBytes,String algorithm)throws Exception {
// <20><><EFBFBD><EFBFBD>X509EncodedKeySpec<65><63><EFBFBD><EFBFBD>
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyBytes);
// ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM.name());
// ȡ<><C8A1>Կ<EFBFBD>׶<EFBFBD><D7B6><EFBFBD>
PublicKey verifyPublicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Signature signature = Signature.getInstance(algorithm);
signature.initVerify(verifyPublicKey);
signature.update(dataBytes);
// verify
return signature.verify(signBytes);
}
/*
* (non-Javadoc)
*
* @see com.connsec.crypto.signature.Signer#verify(java.lang.String,
* java.lang.String, java.lang.String)
*/
public boolean verify(byte[] dataBytes, byte[] publicKeyBytes , byte[] signBytes)throws Exception {
// verify
return verify(dataBytes,publicKeyBytes,signBytes,SIGNATURE_ALGORITHM);
}
/*
* (non-Javadoc)
* @param publicKey is base64
* @param sign is base64
* @see com.connsec.crypto.signature.Signer#verify(java.lang.String,
* java.lang.String, java.lang.String)
*/
public boolean verifyB64(String data, String publicKey, String sign)throws Exception {
// <20><><EFBFBD>ܹ<EFBFBD>Կ
byte[] keyBytes = Base64Utils.decoder(publicKey);
byte[] dataBytes = data.getBytes();
byte[] signBytes=Base64Utils.decoder(sign);
// <20><>֤ǩ<D6A4><C7A9><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>
return verify(dataBytes,keyBytes,signBytes);
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.json;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* JSON deserializer for Jackson to handle regular date instances as timestamps
* in ISO format.
*
*/
public class JsonDateDeserializer extends JsonDeserializer<Date> {
private static final SimpleDateFormat dateFormat =
new SimpleDateFormat("yyyy-MM-dd");
@Override
public Date deserialize(JsonParser parser, DeserializationContext context)
throws IOException, JsonProcessingException {
try {
return dateFormat.parse(parser.getText());
} catch (ParseException e) {
throw new JsonParseException(parser,"Could not parse date", e);
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.json;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.stereotype.Component;
/**
* 日期json序列化格式.
*
* @author Crystal.Sea
*
*/
@Component
public class JsonDateSerializer extends JsonSerializer<Date> {
private static final SimpleDateFormat dateFormat =
new SimpleDateFormat("yyyy-MM-dd");
@Override
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider)
throws IOException, JsonProcessingException {
String formattedDate = dateFormat.format(date);
gen.writeString(formattedDate);
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.json;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.stereotype.Component;
@Component
public class JsonDateTimeDeserializer extends JsonDeserializer<Date> {
private static final SimpleDateFormat dateFormat =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public Date deserialize(JsonParser parser, DeserializationContext dc)
throws IOException, JsonProcessingException {
Date parserDate = null;
try {
parserDate = dateFormat.parse(parser.getText());
} catch (ParseException e) {
throw new JsonParseException(parser,"Could not parse date", e);
}
return parserDate;
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.json;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.stereotype.Component;
/**
* 日期时间json序列化格式.
*
* @author Crystal.Sea
*
*/
@Component
public class JsonDateTimeSerializer extends JsonSerializer<Date> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider)
throws IOException, JsonProcessingException {
String formattedDate = dateFormat.format(date);
gen.writeString(formattedDate);
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.json;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* JSON deserializer for Jackson to handle regular date instances as timestamps
* in ISO format.
*
*/
public class JsonISODateDeserializer extends JsonDeserializer<Date> {
private static final SimpleDateFormat dateFormat =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
@Override
public Date deserialize(JsonParser parser, DeserializationContext context)
throws IOException, JsonProcessingException {
try {
return dateFormat.parse(parser.getText());
} catch (ParseException e) {
throw new JsonParseException(parser,"Could not parse date", e);
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.json;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* JSON serializer for Jackson to handle regular date instances as timestamps in
* ISO format.
*/
public class JsonISODateSerializer extends JsonSerializer<Date> {
private static final SimpleDateFormat dateFormat =
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
@Override
public void serialize(Date date, JsonGenerator generator, SerializerProvider provider)
throws IOException, JsonProcessingException {
String formatted = dateFormat.format(date);
generator.writeString(formatted);
}
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.pretty;
public interface Pretty {
public String format(String source);
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.pretty;
import org.maxkey.pretty.impl.JsonPretty;
import org.maxkey.pretty.impl.SqlPretty;
import org.maxkey.pretty.impl.XmlPretty;
public class PrettyFactory {
static final Pretty jsonPretty = new JsonPretty();
static final Pretty sqlPretty = new SqlPretty();
static final Pretty xmlPretty = new XmlPretty();
public static Pretty getJsonPretty() {
return jsonPretty;
}
public static Pretty getXmlPretty() {
return xmlPretty;
}
public static Pretty getSqlPretty() {
return sqlPretty;
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.pretty.impl;
import java.io.IOException;
import org.maxkey.pretty.Pretty;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParser;
public class JsonPretty implements Pretty{
public JsonPretty() {
}
/**
* prettyJson use jackson
* @param bean
* @return String
*/
public String jacksonFormat(Object bean){
String prettyJson="";
try {
prettyJson= (new ObjectMapper()).writerWithDefaultPrettyPrinter().writeValueAsString(bean);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return prettyJson;
}
/**
* prettyJson use Gson
* @param bean
* @return String
*/
public String format(Object bean){
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(bean);
return json;
}
/**
* prettyJson use Gson
* @param JSON String
* @return String
*/
public String format(String jsonString){
return format(JsonParser.parseString(jsonString));
}
}

View File

@@ -0,0 +1,405 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.pretty.impl;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;
import org.maxkey.pretty.Pretty;
public class SqlPretty implements Pretty{
public static final String WHITESPACE = " \n\r\f\t";
private static final Set<String> BEGIN_CLAUSES = new HashSet<String>();
private static final Set<String> END_CLAUSES = new HashSet<String>();
private static final Set<String> LOGICAL = new HashSet<String>();
private static final Set<String> QUANTIFIERS = new HashSet<String>();
private static final Set<String> DML = new HashSet<String>();
private static final Set<String> MISC = new HashSet<String>();
static {
BEGIN_CLAUSES.add( "left" );
BEGIN_CLAUSES.add( "right" );
BEGIN_CLAUSES.add( "inner" );
BEGIN_CLAUSES.add( "outer" );
BEGIN_CLAUSES.add( "group" );
BEGIN_CLAUSES.add( "order" );
END_CLAUSES.add( "where" );
END_CLAUSES.add( "set" );
END_CLAUSES.add( "having" );
END_CLAUSES.add( "join" );
END_CLAUSES.add( "from" );
END_CLAUSES.add( "by" );
END_CLAUSES.add( "join" );
END_CLAUSES.add( "into" );
END_CLAUSES.add( "union" );
LOGICAL.add( "and" );
LOGICAL.add( "or" );
LOGICAL.add( "when" );
LOGICAL.add( "else" );
LOGICAL.add( "end" );
QUANTIFIERS.add( "in" );
QUANTIFIERS.add( "all" );
QUANTIFIERS.add( "exists" );
QUANTIFIERS.add( "some" );
QUANTIFIERS.add( "any" );
DML.add( "insert" );
DML.add( "update" );
DML.add( "delete" );
MISC.add( "select" );
MISC.add( "on" );
}
private static final String INDENT_STRING = " ";
//mhshi modify
private static final String INITIAL = "";//System.lineSeparator() + INDENT_STRING;
public SqlPretty() {
}
@Override
public String format(String source) {
return new FormatProcess( source ).perform();
}
private static class FormatProcess {
boolean beginLine = true;
boolean afterBeginBeforeEnd;
boolean afterByOrSetOrFromOrSelect;
boolean afterValues;
boolean afterOn;
boolean afterBetween;
boolean afterInsert;
int inFunction;
int parensSinceSelect;
private LinkedList<Integer> parenCounts = new LinkedList<Integer>();
private LinkedList<Boolean> afterByOrFromOrSelects = new LinkedList<Boolean>();
//mhshi modify
int indent = 0;//1;
StringBuilder result = new StringBuilder();
StringTokenizer tokens;
String lastToken;
String token;
String lcToken;
public FormatProcess(String sql) {
tokens = new StringTokenizer(
sql,
"()+*/-=<>'`\"[]," + WHITESPACE,
true
);
}
public String perform() {
result.append( INITIAL );
while ( tokens.hasMoreTokens() ) {
token = tokens.nextToken();
lcToken = token.toLowerCase(Locale.ROOT);
if ( "'".equals( token ) ) {
String t;
do {
t = tokens.nextToken();
token += t;
}
// cannot handle single quotes
while ( !"'".equals( t ) && tokens.hasMoreTokens() );
}
else if ( "\"".equals( token ) ) {
String t;
do {
t = tokens.nextToken();
token += t;
}
while ( !"\"".equals( t ) && tokens.hasMoreTokens() );
}
// SQL Server uses "[" and "]" to escape reserved words
// see SQLServerDialect.openQuote and SQLServerDialect.closeQuote
else if ( "[".equals( token ) ) {
String t;
do {
t = tokens.nextToken();
token += t;
}
while ( !"]".equals( t ) && tokens.hasMoreTokens());
}
if ( afterByOrSetOrFromOrSelect && ",".equals( token ) ) {
commaAfterByOrFromOrSelect();
}
else if ( afterOn && ",".equals( token ) ) {
commaAfterOn();
}
else if ( "(".equals( token ) ) {
openParen();
}
else if ( ")".equals( token ) ) {
closeParen();
}
else if ( BEGIN_CLAUSES.contains( lcToken ) ) {
beginNewClause();
}
else if ( END_CLAUSES.contains( lcToken ) ) {
endNewClause();
}
else if ( "select".equals( lcToken ) ) {
select();
}
else if ( DML.contains( lcToken ) ) {
updateOrInsertOrDelete();
}
else if ( "values".equals( lcToken ) ) {
values();
}
else if ( "on".equals( lcToken ) ) {
on();
}
else if ( afterBetween && lcToken.equals( "and" ) ) {
misc();
afterBetween = false;
}
else if ( LOGICAL.contains( lcToken ) ) {
logical();
}
else if ( isWhitespace( token ) ) {
white();
}
else {
misc();
}
if ( !isWhitespace( token ) ) {
lastToken = lcToken;
}
}
return result.toString();
}
private void commaAfterOn() {
out();
indent--;
newline();
afterOn = false;
afterByOrSetOrFromOrSelect = true;
}
private void commaAfterByOrFromOrSelect() {
out();
newline();
}
private void logical() {
if ( "end".equals( lcToken ) ) {
indent--;
}
newline();
out();
beginLine = false;
}
private void on() {
indent++;
afterOn = true;
newline();
out();
beginLine = false;
}
private void misc() {
out();
if ( "between".equals( lcToken ) ) {
afterBetween = true;
}
if ( afterInsert ) {
newline();
afterInsert = false;
}
else {
beginLine = false;
if ( "case".equals( lcToken ) ) {
indent++;
}
}
}
private void white() {
if ( !beginLine ) {
result.append( " " );
}
}
private void updateOrInsertOrDelete() {
out();
indent++;
beginLine = false;
if ( "update".equals( lcToken ) ) {
newline();
}
if ( "insert".equals( lcToken ) ) {
afterInsert = true;
}
}
private void select() {
out();
indent++;
newline();
parenCounts.addLast( parensSinceSelect );
afterByOrFromOrSelects.addLast( afterByOrSetOrFromOrSelect );
parensSinceSelect = 0;
afterByOrSetOrFromOrSelect = true;
}
private void out() {
result.append( token );
}
private void endNewClause() {
if ( !afterBeginBeforeEnd ) {
indent--;
if ( afterOn ) {
indent--;
afterOn = false;
}
newline();
}
out();
if ( !"union".equals( lcToken ) ) {
indent++;
}
newline();
afterBeginBeforeEnd = false;
afterByOrSetOrFromOrSelect = "by".equals( lcToken )
|| "set".equals( lcToken )
|| "from".equals( lcToken );
}
private void beginNewClause() {
if ( !afterBeginBeforeEnd ) {
if ( afterOn ) {
indent--;
afterOn = false;
}
indent--;
newline();
}
out();
beginLine = false;
afterBeginBeforeEnd = true;
}
private void values() {
indent--;
newline();
out();
indent++;
newline();
afterValues = true;
}
private void closeParen() {
parensSinceSelect--;
if ( parensSinceSelect < 0 ) {
indent--;
parensSinceSelect = parenCounts.removeLast();
afterByOrSetOrFromOrSelect = afterByOrFromOrSelects.removeLast();
}
if ( inFunction > 0 ) {
inFunction--;
out();
}
else {
if ( !afterByOrSetOrFromOrSelect ) {
indent--;
newline();
}
out();
}
beginLine = false;
}
private void openParen() {
if ( isFunctionName( lastToken ) || inFunction > 0 ) {
inFunction++;
}
beginLine = false;
if ( inFunction > 0 ) {
out();
}
else {
out();
if ( !afterByOrSetOrFromOrSelect ) {
indent++;
newline();
beginLine = true;
}
}
parensSinceSelect++;
}
private static boolean isFunctionName(String tok) {
if ( tok == null || tok.length() == 0 ) {
return false;
}
final char begin = tok.charAt( 0 );
final boolean isIdentifier = Character.isJavaIdentifierStart( begin ) || '"' == begin;
return isIdentifier &&
!LOGICAL.contains( tok ) &&
!END_CLAUSES.contains( tok ) &&
!QUANTIFIERS.contains( tok ) &&
!DML.contains( tok ) &&
!MISC.contains( tok );
}
private static boolean isWhitespace(String token) {
return WHITESPACE.contains( token );
}
private void newline() {
result.append( System.lineSeparator() );
for ( int i = 0; i < indent; i++ ) {
result.append( INDENT_STRING );
}
beginLine = true;
}
}
}

View File

@@ -0,0 +1,267 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.pretty.impl;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;
import org.w3c.dom.ls.LSSerializerFilter;
import org.xml.sax.InputSource;
import net.shibboleth.utilities.java.support.collection.LazyMap;
public class XMLHelper {
/**
* A string which contains the valid delimiters for the XML Schema 'list' type. These are: space, newline, carriage
* return, and tab.
*/
public static final String LIST_DELIMITERS = " \n\r\t";
/** DOM configuration parameters used by LSSerializer in pretty print format output. */
private static Map<String, Object> prettyPrintParams;
/**
* Converts a Node into a String using the DOM, level 3, Load/Save serializer.
*
* @param node the node to be written to a string
*
* @return the string representation of the node
*/
public static String nodeToString(Node node) {
StringWriter writer = new StringWriter();
writeNode(node, writer);
return writer.toString();
}
/**
* Pretty prints the XML node.
*
* @param node xml node to print
*
* @return pretty-printed xml
*/
public static String prettyPrintXML(Node node) {
StringWriter writer = new StringWriter();
writeNode(node, writer, getPrettyPrintParams());
return writer.toString();
}
public static String prettyPrintXML(String xmlString){
try{
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(new InputSource(new StringReader(xmlString)));
return prettyPrintXML(document);
}catch(Exception e){
e.printStackTrace();
return null;
}
}
/**
* Create the parameters set used in pretty print formatting of an LSSerializer.
*
* @return the params map
*/
private static Map<String, Object> getPrettyPrintParams() {
if (prettyPrintParams == null) {
prettyPrintParams = new LazyMap<String, Object>();
prettyPrintParams.put("format-pretty-print", Boolean.TRUE);
}
return prettyPrintParams;
}
/**
* Writes a Node out to a Writer using the DOM, level 3, Load/Save serializer. The written content is encoded using
* the encoding specified in the writer configuration.
*
* @param node the node to write out
* @param output the writer to write the XML to
*/
public static void writeNode(Node node, Writer output) {
writeNode(node, output, null);
}
/**
* Writes a Node out to a Writer using the DOM, level 3, Load/Save serializer. The written content is encoded using
* the encoding specified in the writer configuration.
*
* @param node the node to write out
* @param output the writer to write the XML to
* @param serializerParams parameters to pass to the {@link DOMConfiguration} of the serializer
* instance, obtained via {@link LSSerializer#getDomConfig()}. May be null.
*/
public static void writeNode(Node node, Writer output, Map<String, Object> serializerParams) {
DOMImplementationLS domImplLS = getLSDOMImpl(node);
LSSerializer serializer = getLSSerializer(domImplLS, serializerParams);
LSOutput serializerOut = domImplLS.createLSOutput();
serializerOut.setCharacterStream(output);
serializer.write(node, serializerOut);
}
/**
* Writes a Node out to an OutputStream using the DOM, level 3, Load/Save serializer. The written content
* is encoded using the encoding specified in the output stream configuration.
*
* @param node the node to write out
* @param output the output stream to write the XML to
*/
public static void writeNode(Node node, OutputStream output) {
writeNode(node, output, null);
}
/**
* Writes a Node out to an OutputStream using the DOM, level 3, Load/Save serializer. The written content
* is encoded using the encoding specified in the output stream configuration.
*
* @param node the node to write out
* @param output the output stream to write the XML to
* @param serializerParams parameters to pass to the {@link DOMConfiguration} of the serializer
* instance, obtained via {@link LSSerializer#getDomConfig()}. May be null.
*/
public static void writeNode(Node node, OutputStream output, Map<String, Object> serializerParams) {
DOMImplementationLS domImplLS = getLSDOMImpl(node);
LSSerializer serializer = getLSSerializer(domImplLS, serializerParams);
LSOutput serializerOut = domImplLS.createLSOutput();
serializerOut.setByteStream(output);
serializer.write(node, serializerOut);
}
/**
* Obtain a the DOM, level 3, Load/Save serializer {@link LSSerializer} instance from the
* given {@link DOMImplementationLS} instance.
*
* <p>
* The serializer instance will be configured with the parameters passed as the <code>serializerParams</code>
* argument. It will also be configured with an {@link LSSerializerFilter} that shows all nodes to the filter,
* and accepts all nodes shown.
* </p>
*
* @param domImplLS the DOM Level 3 Load/Save implementation to use
* @param serializerParams parameters to pass to the {@link DOMConfiguration} of the serializer
* instance, obtained via {@link LSSerializer#getDomConfig()}. May be null.
*
* @return a new LSSerializer instance
*/
public static LSSerializer getLSSerializer(DOMImplementationLS domImplLS, Map<String, Object> serializerParams) {
LSSerializer serializer = domImplLS.createLSSerializer();
serializer.setFilter(new LSSerializerFilter() {
public short acceptNode(Node arg0) {
return FILTER_ACCEPT;
}
public int getWhatToShow() {
return SHOW_ALL;
}
});
if (serializerParams != null) {
DOMConfiguration serializerDOMConfig = serializer.getDomConfig();
for (String key : serializerParams.keySet()) {
serializerDOMConfig.setParameter(key, serializerParams.get(key));
}
}
return serializer;
}
/**
* Get the DOM Level 3 Load/Save {@link DOMImplementationLS} for the given node.
*
* @param node the node to evaluate
* @return the DOMImplementationLS for the given node
*/
public static DOMImplementationLS getLSDOMImpl(Node node) {
DOMImplementation domImpl;
if (node instanceof Document) {
domImpl = ((Document) node).getImplementation();
} else {
domImpl = node.getOwnerDocument().getImplementation();
}
DOMImplementationLS domImplLS = (DOMImplementationLS) domImpl.getFeature("LS", "3.0");
return domImplLS;
}
public static String transformer(Element element) {
String xmlString = null;
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(element);
transformer.transform(source, result);
xmlString = result.getWriter().toString();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
return xmlString;
}
public static String transformer(String xmlString){
try{
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(new InputSource(new StringReader(xmlString)));
return transformer(document.getDocumentElement());
}catch(Exception e){
e.printStackTrace();
return null;
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.pretty.impl;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.maxkey.pretty.Pretty;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
public class XmlPretty implements Pretty{
public XmlPretty() {
}
@Override
public String format(String xmlString){
try{
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(new InputSource(new StringReader(xmlString)));
return format(document);
}catch(Exception e){
e.printStackTrace();
return null;
}
}
public String format(Node node){
try{
return XMLHelper.prettyPrintXML(node);
}catch(Exception e){
e.printStackTrace();
return null;
}
}
}

View File

@@ -0,0 +1,22 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author mhshi
*
*/
package org.maxkey.pretty.impl;

View File

@@ -0,0 +1,78 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.util;
import org.maxkey.crypto.Base64Utils;
/**
* @author Crystal.Sea
*
*/
public class AuthorizationHeaderUtils {
public static final String AUTHORIZATION_HEADERNAME = "Authorization";
public static final String BASIC = "Basic ";
public static final String BEARER = "Bearer ";
public static String createBasic(String username, String password) {
String authUserPass = username + ":" + password;
String encodedAuthUserPass = Base64Utils.encode(authUserPass);
return BASIC + encodedAuthUserPass;
}
public static String[] resolveBasic(String basic) {
if (isBasic(basic)) {
String[] userPass = basic.split(" ");
String decodeUserPass = Base64Utils.decode(userPass[1]);
return decodeUserPass.split(":");
} else {
return null;
}
}
public static boolean isBasic(String basic) {
if (basic.startsWith(BASIC)) {
return true;
} else {
return false;
}
}
public static String resolveBearer(String bearer) {
if (isBearer(bearer)) {
return bearer.split(" ")[1];
} else {
return null;
}
}
public static String createBearer(String bearer) {
return BEARER + bearer;
}
public static boolean isBearer(String bearer) {
if (bearer.startsWith(BEARER)) {
return true;
} else {
return false;
}
}
}

View File

@@ -0,0 +1,127 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.util;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.logging.LogFactory;
/**
* @author Crystal
*
*/
public class BeanConvert {
/**
*
*/
public BeanConvert() {
}
public static <T> Map<String, Object> bean2Map( T bean){
Map <String,Object> mapBean=new HashMap<String,Object>();
Field[] flds = bean.getClass().getDeclaredFields();
LogFactory.getLog(BeanConvert.class).debug("bean2Map() *******************************************");
LogFactory.getLog(BeanConvert.class).debug("bean2Map() "+bean.getClass().getName());
for (int i = 0; i < flds.length; i++) {
String fieldName = flds[i].getName();
if(BeanUtil.isGetProperty(bean.getClass(),fieldName)){
Object value=BeanUtil.get(bean, fieldName);
mapBean.put(fieldName,value );
LogFactory.getLog(BeanConvert.class).debug("bean2Map() field "+(i+1)+" : "+fieldName+" = "+value+" type : "+flds[i].getType());
}
}
LogFactory.getLog(BeanConvert.class).debug("bean2Map() *******************************************");
return mapBean;
}
public static <T> Object map2Bean(T bean,HashMap<?, ?> valueMap){
Map<?, ?> beanFiledMap=null;
try {
beanFiledMap = BeanUtil.getFields(bean);
} catch (Exception e) {
e.printStackTrace();
}
if(beanFiledMap==null)return bean;
Iterator<?> fieldit = beanFiledMap.entrySet().iterator();
LogFactory.getLog(BeanConvert.class).debug("map2Bean() *******************************************");
LogFactory.getLog(BeanConvert.class).debug("map2Bean() "+bean.getClass().getName());
int i=1;
while (fieldit.hasNext()) {
Map.Entry entry = (Map.Entry) fieldit.next();
String fieldName = entry.getKey().toString();
Object value = null;
String fieldType=(String)beanFiledMap.get(fieldName);
if(valueMap.get(fieldName)==null)continue;
String fillValue=valueMap.get(fieldName).toString();
LogFactory.getLog(BeanConvert.class).debug("map2Bean() field "+(i++)+" : "+fieldName+" = "+fillValue+" type : "+fieldType);
if(fieldType.equals("java.lang.String")){
value=String.valueOf(fillValue);
}else if(fieldType.equals("int")){
value=Integer.parseInt(fillValue);
}else if(fieldType.equals("java.lang.Integer")){
value=Integer.parseInt(fillValue);
}else if(fieldType.equals("long")){
value=Long.parseLong(fillValue);
}else if(fieldType.equals("java.lang.Long")){
value=new Long(fillValue);
}else if(fieldType.equals("double")){
value=(double)Double.valueOf(fillValue);
}else if(fieldType.equals("java.lang.Double")){
value=Double.valueOf(fillValue);
}else if(fieldType.equals("float")){
value=Float.parseFloat(fillValue);
}else if(fieldType.equals("java.lang.Float")){
value=Float.parseFloat(fillValue);
}else if(fieldType.equals("java.util.Date")){
try {
if(fillValue.length()==10){
fillValue+=" 00:00:00";
value=(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss")).parse(fillValue);
}else{
continue;
}
} catch (ParseException e) {
e.printStackTrace();
}
}else if(fieldType.equals("java.lang.Object")){
value=valueMap.get(fieldName);
}else if(fieldType.equals("char")){
value=Character.valueOf(fillValue.charAt(0));
}else if(fieldType.equals("boolean")){
value=Boolean.parseBoolean(fillValue);
}else if(fieldType.equals("short")){
value=Short.parseShort(fillValue);
}else if(fieldType.equals("byte")){
value=Byte.parseByte(fillValue);
}
BeanUtil.set(bean, fieldName, value);
}
LogFactory.getLog(BeanConvert.class).debug("map2Bean() *******************************************");
return bean;
}
}

View File

@@ -0,0 +1,335 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.util;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.LogFactory;
public class BeanUtil {
public static void copyBean(Object origin,Object target) {
if( origin == null || target == null) return;
try {
BeanUtils.copyProperties( origin, target);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Object cloneSupper(Object origin) {
Object target = null;
if(origin == null) return target;
try {
target = origin.getClass().getSuperclass().newInstance();
BeanUtils.copyProperties(target,origin);
} catch (Exception e) {
e.printStackTrace();
}
return target;
}
public static String getValue(Object bean,String field ) {
if(bean == null) return null;
String retVal = "";
try {
retVal = BeanUtils.getProperty(bean, field);
} catch(Exception e) {
e.printStackTrace();
}
return retVal;
}
@SuppressWarnings("rawtypes")
public static boolean isNotNull(Collection collection) {
if(collection != null && collection.size() > 0) {
return true;
}
return false;
}
@SuppressWarnings("rawtypes")
public static boolean isNotNull(Map map) {
if(map != null && map.size() > 0) {
return true;
}
return false;
}
public static Object get(Object bean, String fieldName) {
try {
return invokeMethod(bean,getMethodByProperty("get",fieldName));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Object set(Object bean, String fieldName,Object value) {
try {
return invokeMethod(bean,getMethodByProperty("set",fieldName),new Object[]{value});
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Object getPublicProperty(Object bean, String fieldName) {
try {
Field field = bean.getClass().getField(fieldName);
return field.get(bean);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static boolean setPublicProperty(Object bean, String fieldName,Object value) {
try {
Field field = bean.getClass().getField(fieldName);
field.set(bean,value);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static Boolean isPublicProperty(Class<? extends Object> cls, String fieldName) {
if (isSetProperty(cls, fieldName)&& isGetProperty(cls, fieldName)) {
return true;
} else {
return false;
}
}
public static Boolean isPublicProperty(Object bean, String fieldName) {
if (isSetProperty(bean.getClass(), fieldName)
&& isGetProperty(bean.getClass(), fieldName)) {
return true;
} else {
return false;
}
}
public static <T> Boolean isSetProperty(Class<T> cls, String fieldName) {
Method[] method = cls.getDeclaredMethods();
for (int i = 0; i < method.length; i++) {
if (method[i].getModifiers() == Modifier.PUBLIC
&& method[i].getName().equals(getMethodByProperty("set",fieldName))) {
return true;
}
}
return false;
}
public static <T> Boolean isGetProperty(Class<T> cls, String fieldName) {
Method[] method = cls.getDeclaredMethods();
for (int i = 0; i < method.length; i++) {
if (method[i].getModifiers() == Modifier.PUBLIC
&& method[i].getName().equals(getMethodByProperty("get",fieldName))) {
return true;
}
}
return false;
}
public static Object newInstance(String className) {
return Instance.newInstance(className);
}
public static <T> Object newInstance(Class<T> cls) {
return Instance.newInstance(cls);
}
public static Object newInstance(String className, Object[] args) {
return Instance.newInstance(className, args);
}
public static <T> T newInstance(Class<T> cls, Object[] args) {
return (T) Instance.newInstance(cls, args);
}
public static Object invokeMethod(Object bean, String methodName, Object[] args)
throws Exception {
return MethodInvoke.invokeMethod(bean, methodName, args);
}
public static Object invokeMethod(Object bean, String methodName)
throws Exception {
return MethodInvoke.invokeMethod(bean, methodName);
}
public static Object invokeStaticMethod(Class<?> beanClass, String methodName,
Object[] args) throws Exception {
return MethodInvoke.invokeMethod(beanClass, methodName, args);
}
public static Object invokeStaticMethod(Class<?> beanClass, String methodName) throws Exception {
return MethodInvoke.invokeStaticMethod(beanClass, methodName);
}
public static Map<?, ?> toMap(Object bean){
return BeanConvert.bean2Map(bean);
}
public static Object fillBean(Object bean,HashMap<?, ?> valueMap){
return BeanConvert.map2Bean(bean, valueMap);
}
public static Map<String, String> getFields(Class<? extends Object> cls) {
Field[] flds = cls.getDeclaredFields();
Map<String, String> map = new HashMap<String, String>();
for (int i = 0; i < flds.length; i++) {
String name = flds[i].getName();
map.put(flds[i].getName(), flds[i].getType().getName());
}
return map;
}
public static Map<String, String> getFields(Object bean) {
return getFields(bean.getClass());
}
public static Map<String, String> getPropertyFields(Class<? extends Object> cls){
Field[] flds = cls.getDeclaredFields();
Map<String, String> map = new HashMap<String, String>();
for (int i = 0; i < flds.length; i++) {
String fieldName = flds[i].getName();
if (isPublicProperty(cls, fieldName))
map.put(flds[i].getName(), flds[i].getType().getName());
}
return map;
}
public static Map<String, String> getPropertyFields(Object bean) {
return getPropertyFields(bean.getClass());
}
public static <T> boolean isEmpty(T entity,Field field){
return ! isNotEmpty(entity,field);
}
public static <T> boolean isNotEmpty(T entity,Field field){
boolean isFieldNotEmpty=true;
String fieldType=field.getType().getName();
Object value=null;
String fillValue=null;
try {
if(BeanUtil.get(entity, field.getName())==null){
return false;
}else{
fillValue = BeanUtil.get(entity, field.getName()).toString();
}
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
}
if(fieldType.equals("java.lang.String")){
if(String.valueOf(fillValue)==null)isFieldNotEmpty= false;
}else if(fieldType.equals("int")){
if(Integer.parseInt(fillValue)==0)isFieldNotEmpty= false;
}else if(fieldType.equals("long")){
if(Long.parseLong(fillValue)==0)isFieldNotEmpty= false;
}else if(fieldType.equals("java.lang.Long")){
if(Long.parseLong(fillValue)==0)isFieldNotEmpty= false;
}else if(fieldType.equals("double")){
if(Double.valueOf(fillValue)==0.0d)isFieldNotEmpty= false;
}else if(fieldType.equals("float")){
if(Float.parseFloat(fillValue)==0.0f)isFieldNotEmpty= false;
}else if(fieldType.equals("java.util.Date")){
try {
value=BeanUtil.get(entity, field.getName());
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
if(value==null)isFieldNotEmpty= false;
}else if(fieldType.equals("java.lang.Object")){
try {
value=BeanUtil.get(entity, field.getName());
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
if(value==null)isFieldNotEmpty= false;
}else if(fieldType.equals("char")){
if(Character.valueOf(fillValue.charAt(0))=='\u0000')isFieldNotEmpty= false;
}else if(fieldType.equals("boolean")){
value=Boolean.parseBoolean(fillValue);
}else if(fieldType.equals("short")){
if(Short.parseShort(fillValue)==0)isFieldNotEmpty= false;
}else if(fieldType.equals("byte")){
if(Byte.parseByte(fillValue)==0)isFieldNotEmpty= false;
}
LogFactory.getLog(BeanUtil.class).debug("isFieldNotEmpty() fieldName : "+field.getName()+", fieldType : "+fieldType+", Value : "+fillValue+", isFieldNotEmpty : "+isFieldNotEmpty);
return isFieldNotEmpty;
}
public static void displayValues(Object bean) {
Field[] flds = bean.getClass().getDeclaredFields();
LogFactory.getLog(BeanUtil.class).debug("displayValues() *******************************************");
LogFactory.getLog(BeanUtil.class).debug("displayValues() "+bean.getClass().getName());
for (int i = 0; i < flds.length; i++) {
String name = flds[i].getName();
if(isGetProperty(bean.getClass(),name)){
LogFactory.getLog(BeanUtil.class).debug("displayValues() Field "+(i+1)+" : "+name+" = "+BeanUtil.get(bean, name));
}
}
LogFactory.getLog(BeanUtils.class).debug("displayValues() *******************************************");
}
public static <T> void beanClone(T target,T origin){
Field[] flds = target.getClass().getDeclaredFields();
for (int i = 0; i < flds.length; i++) {
String name = flds[i].getName();
if(isPublicProperty(origin,name)){
if(get(origin,name)!=null){
set(target,name,get(origin,name));
}
}
}
}
public static Class[] getMethodParameterTypes(Class<?> c,String methodName){
Method []methods=c.getMethods();
for (Method method : methods) {
Class[] parameterTypes = method.getParameterTypes();
if(method.getName().equals(methodName)){
return parameterTypes;
}
}
return null;
}
public static String getMethodByProperty(String getOrSet ,String property){
String methodName=getOrSet+(
property.length() == 1 ?
(Character.toUpperCase(property.charAt(0)) + "") :
Character.toUpperCase(
property.charAt(0))+ property.substring(1));
//LogFactory.getLog(BeanUtils.class).debug("getMethodByProperty() methodName : "+methodName);
return methodName;
}
}

View File

@@ -0,0 +1,660 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.util;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.chrono.ISOChronology;
public class DateUtils {
public final static String FORMAT_DATE_DEFAULT = "yyyy-MM-dd";
public final static String FORMAT_DATE_YYYYMMDD = "yyyyMMdd";
public final static String FORMAT_DATE_YYYY_MM_DD = "yyyy-MM-dd";
public final static String FORMAT_DATE_PATTERN_1="yyyy/MM/dd";
public final static String FORMAT_DATE_PATTERN_2="yyyy/M/dd";
public final static String FORMAT_DATE_PATTERN_3="yyyy/MM/d";
public final static String FORMAT_DATE_PATTERN_4="yyyy/M/d";
public final static String FORMAT_DATE_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
public final static String FORMAT_DATE_ISO_TIMESTAMP="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
public final static String FORMAT_DATE_YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
public final static String FORMAT_DATE_YYYY_MM_DD_HHMM = "yyyy-MM-dd HHmm";
public final static String FORMAT_DATE_YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
public final static String FORMAT_DATE_HH_MM = "HH:mm";
public final static String FORMAT_DATE_HH_MM_SS = "HH:mm:ss";
public final static String FORMAT_DATE_HHMM = "HHmm";
public final static String FORMAT_DATE_HHMMSS = "HHmmss";
public static final String FORMAT_WORK_TIME = "yyyy-MM-dd HHmmss";
/**
* Compares two Dates from their string value.
*
* @param stringValue1
* Date 1 as string value.
* @param stringValue2
* Date 2 as string value.
*
* @return the value <code>0</code> if the argument stringValue1 is equal
* to stringValue2; a value less than <code>0</code> if this
* stringValue1 is before the stringValue2 as Date; and a value
* greater than <code>0</code> if this stringValue1 is after the
* stringValue2.
* @since 1.2
*/
public final static int compareDate(String stringValue1, String stringValue2)
throws ParseException {
Date date1 = tryParse(stringValue1);
if (date1 == null)
throw new ParseException("Can not parse " + stringValue1
+ " to Date.", 0);
Date date2 = tryParse(stringValue2);
if (date2 == null)
throw new ParseException("Can not parse " + stringValue1
+ " to Date.", 0);
return date1.compareTo(date2);
}
/**
* Returns current system date as formatted string value with default format
* pattern.
*
* @return current system date.
*
* @see #FORMAT_DATE_DEFAULT
*/
public final static String getCurrentDateAsString() {
return getCurrentDateAsString(FORMAT_DATE_DEFAULT);
}
public final static String getCurrentDateTimeAsString() {
return getCurrentDateAsString(FORMAT_DATE_YYYY_MM_DD_HH_MM_SS);
}
/**
* Returns current system date as formatted string value with given format
* pattern.
*
* @param formatPattern
* format pattern.
* @return current system date.
*
*/
public final static String getCurrentDateAsString(String formatPattern) {
Date date = new Date();
return format(date, formatPattern);
}
public final static String getFormtPattern1ToPattern2(String stringValue,String formatPattern1,String formatPattern2){
Date date = parse(stringValue, formatPattern1);
return format(date, formatPattern2);
}
/**
* Returns current system date.
*
* @return current system date.
*/
public final static Date getCurrentDate() {
return new Date();
}
/**
* 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, 1<><31><EFBFBD><EFBFBD>һ, 2<><32><EFBFBD>ڶ<EFBFBD>, 3<><33><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, 4<><34><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, 5<><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,6<><36><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @return
*/
public final static String getTodayOfWeek(){
Calendar calendar = Calendar.getInstance();
Date date = new Date();
calendar.setTime(date);
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)-1;
return dayOfWeek+"";
}
/**
* <20>Ƚ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD> 6:00-12:00
* @param startTime
* @param endTime
* @return
*/
public final static boolean compareTime(String startTime,String endTime) throws ParseException{
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
Date start = sdf.parse(startTime);
Date end = sdf.parse(endTime);
if(start.before(end)){
return true;
}
return false;
}
/**
* 判断value时间值是否在date时间之前
* @param value
* @param date
* @param datePattern
* @return
*/
public static boolean compareTime(String endDate,Date startDate,String datePattern) {
Date valueDate = DateUtils.parse(endDate, datePattern);
return valueDate.before(startDate);
}
/**
* Format Date value as string value with default format pattern.
*
* @param date
* Date value.
* @return formatted date as string value.
*
* @see #FORMAT_DATE_DEFAULT
*/
public final static String format(Date date) {
if (date == null) {
return "";
}
return format(date, FORMAT_DATE_DEFAULT);
}
/**
* Format Date value as string value with default format pattern.
*
* @param date
* Date value.
* @return formatted date as string value.
*
* @see #FORMAT_DATE_DEFAULT
*/
public final static String formatDateTime(Date date) {
if (date == null) {
return "";
}
return format(date, FORMAT_DATE_YYYY_MM_DD_HH_MM_SS);
}
/**
* Format Date value as string value with default format pattern.
*
* @param date
* Date value.
* @return formatted date as string value.
*
* @see #FORMAT_DATE_DEFAULT
*/
public final static String formatTimestamp(Date date) {
if (date == null) {
return "";
}
return format(date, "yyyy-MM-dd HH:mm:ss.SSS");
}
/**
* Format Date value as string value with default format pattern.
*
* @param date
* Date value.
* @return formatted date as string value.
*
* @see #FORMAT_DATE_DEFAULT
*/
public final static Date parseTimestamp(String date) {
if (date == null) {
return null;
}
return parse(date, "yyyy-MM-dd HH:mm:ss.SSS");
}
/**
* Format Date value as string value with given format pattern.
*
* @param date
* Date value.
* @param formatPattern
* format pattern.
* @return formatted date as string value.
*
* @see #FORMAT_DATE_DEFAULT
* @see #FORMAT_DATE_YYYY_MM_DD
* @see #FORMAT_DATE_YYYY_MM_DD_HH_MM
* @see #FORMAT_DATE_YYYY_MM_DD_HH_MM_SS
* @see #FORMAT_DATE_YYYY_MM_DD_HHMMSS
*/
public final static String format(Date date, String formatPattern) {
if (date == null) {
return "";
}
return new SimpleDateFormat(formatPattern).format(date);
}
/**
* Parse string value to Date with default format pattern.
*
* @param stringValue
* date value as string.
* @return Date represents stringValue.
* @see #FORMAT_DATE_DEFAULT
*/
public final static Date parse(String stringValue) {
return parse(stringValue, FORMAT_DATE_DEFAULT);
}
/**
* Parse string value to Date with given format pattern.
*
* @param stringValue
* date value as string.
* @param formatPattern
* format pattern.
* @return Date represents stringValue, null while parse exception occurred.
* @see #FORMAT_DATE_DEFAULT
*/
public final static Date parse(String stringValue, String formatPattern) {
SimpleDateFormat format = new SimpleDateFormat(formatPattern);
try {
return format.parse(stringValue);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
/**
* Try to parse string value to date.
*
* @param stringValue
* string value.
* @return Date represents stringValue, null while parse exception occurred.
*/
public final static Date tryParse(String stringValue) {
Date date = parse(stringValue, FORMAT_DATE_YYYY_MM_DD);
if (date != null) {
return date;
}
date = parse(stringValue, FORMAT_DATE_YYYYMMDD);
if (date != null) {
return date;
}
date = parse(stringValue, FORMAT_DATE_YYYYMMDDHHMMSS);
if (date != null) {
return date;
}
date = parse(stringValue, FORMAT_DATE_YYYY_MM_DD_HH_MM_SS);
if (date != null) {
return date;
}
date = parse(stringValue, FORMAT_DATE_YYYY_MM_DD_HHMM);
if (date != null) {
return date;
}
date = parse(stringValue,FORMAT_DATE_PATTERN_1);
if (date != null) {
return date;
}
date=parse(stringValue, FORMAT_DATE_PATTERN_2);
if (date != null) {
return date;
}
date=parse(stringValue, FORMAT_DATE_PATTERN_3);
if (date != null) {
return date;
}
date=parse(stringValue, FORMAT_DATE_PATTERN_4);
if (date != null) {
return date;
}
return date;
}
/**
* get day of week
* @param SUN_FST_DAY_OF_WEEK
* @return
*/
public static int getDayOfWeek(int SUN_FST_DAY_OF_WEEK) {
if (SUN_FST_DAY_OF_WEEK > 7 || SUN_FST_DAY_OF_WEEK < 1)
return 0;
if (SUN_FST_DAY_OF_WEEK == 1)
return 7;
return SUN_FST_DAY_OF_WEEK - 1;
}
public static Timestamp parseTimestamp(String stringValue,
String formatPattern) {
return new Timestamp(parse(stringValue, formatPattern).getTime());
}
public static Timestamp parseTimestamp(Date d) {
return new Timestamp(d.getTime());
}
//-----------------------------------------------------------------------
/**
* Adds a number of milliseconds to a date returning a new object.
* The original date object is unchanged.
*
* @param date the date, not null
* @param amount the amount to add, may be negative
* @return the new date object with the amount added
* @throws IllegalArgumentException if the date is null
*/
public static Date addMilliseconds(Date date, int amount) {
return add(date, Calendar.MILLISECOND, amount);
}
//-----------------------------------------------------------------------
/**
* Adds a number of minutes to a date returning a new object.
* The original date object is unchanged.
*
* @param date the date, not null
* @param amount the amount to add, may be negative
* @return the new date object with the amount added
* @throws IllegalArgumentException if the date is null
*/
public static Date addMinutes(Date date, int amount) {
return add(date, Calendar.MINUTE, amount);
}
//-----------------------------------------------------------------------
/**
* Adds to a date returning a new object.
* The original date object is unchanged.
*
* @param date the date, not null
* @param calendarField the calendar field to add to
* @param amount the amount to add, may be negative
* @return the new date object with the amount added
* @throws IllegalArgumentException if the date is null
*
*/
public static Date add(Date date, int calendarField, int amount) {
if (date == null) {
throw new IllegalArgumentException("The date must not be null");
}
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(calendarField, amount);
return c.getTime();
}
public static String getExchangeFormat(String dateStr,String sourFormat,String destFormat){
String dt="";
try{
SimpleDateFormat sdf=new SimpleDateFormat(destFormat);
dt=sdf.format(parse(dateStr,sourFormat));
}catch(Exception e){
e.printStackTrace();
}
return dt;
}
public static Date plugOneDate(Date date) {
return new Date(date.getTime() + 24*60*60*1000L);
}
/**
* <20><><EFBFBD>date<74>ĺ<EFBFBD>һ<EFBFBD><EFBFBD><ECA3AC>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ֱ<EFBFBD>Ϊ00:00:00
* @param date
* @return
*/
public static Date getNextDay(Date date) {
Date nextDay = new Date(date.getTime() + 24*60*60*1000L);
// Get Calendar object set to the date and time of the given Date object
Calendar cal = Calendar.getInstance();
cal.setTime(nextDay);
// Set time fields to zero
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
// Put it back in the Date object
nextDay = cal.getTime();
return nextDay;
}
/**
* ɾ<><C9BE>date<74>е<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EBA1A2><EFBFBD><EFBFBD>
*
* @param date
* @return
*/
public static Date truncateTime(Date date) {
if (date == null) {
return null;
}
Calendar c = Calendar.getInstance();
c.setTime(date);
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
return c.getTime();
}
/**
* <20>Ը<EFBFBD>ʱ<EFBFBD><CAB1>date<74><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD>(<28><>ǰ<EFBFBD>ƶ<EFBFBD>)<29><><EFBFBD><EFBFBD>
*
* @param date
* @param year
* @param month
* @param day
* @param hour
* @param minute
* @param second
* @param milliSecond
* @return
*/
public static Date addDate(Date date, int year, int month, int day, int hour, int minute, int second, int milliSecond) {
if (date == null) {
return null;
}
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.YEAR, year);
c.add(Calendar.MONTH, month);
c.add(Calendar.DATE, day);
c.add(Calendar.HOUR_OF_DAY, hour);
c.add(Calendar.MINUTE, minute);
c.add(Calendar.SECOND, second);
c.add(Calendar.MILLISECOND, milliSecond);
return c.getTime();
}
public static Date addDate(Date date, int year, int month, int day, int hour, int minute, int second) {
return addDate(date, year, month, day, hour, minute, second, 0);
}
public static Date addDate(Date date, int hour, int minute, int second) {
return addDate(date, 0, 0, 0, hour, minute, second, 0);
}
/**
* <20><><EFBFBD><EFBFBD>day1<79><31>day2<79><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(day1-day2)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* @param day1
* @param day2
* @return
*/
public static int getIntervalDays(Date day1, Date day2) {
if (day1 == null || day2 == null) {
throw new IllegalArgumentException("Argument day1 or day2 must be not null.");
}
Date day1ToUse = truncateTime(day1);
Date day2ToUse = truncateTime(day2);
long intervalMilliSecond = getIntervalMilliSeconds(day1ToUse, day2ToUse);
return (int) (intervalMilliSecond / (24 * 60 * 60 * 1000));
}
/**
* <20><><EFBFBD><EFBFBD>day1<79><31>day2<79><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(day1-day2)<29><><EFBFBD>·<EFBFBD>
*
* @param day1
* @param day2
* @return
*/
public static int getIntervalMonths(Date day1, Date day2) {
if (day1 == null || day2 == null) {
throw new IllegalArgumentException("Argument day1 or day2 must be not null.");
}
Calendar calDay1 = Calendar.getInstance();
calDay1.setTime(day1);
Calendar calDay2 = Calendar.getInstance();
calDay2.setTime(day2);
int yearInterval = calDay1.get(Calendar.YEAR) - calDay2.get(Calendar.YEAR);
int monthInterval = calDay1.get(Calendar.MONTH) - calDay2.get(Calendar.MONTH);
return yearInterval * 12 + monthInterval;
}
/**
* <20><><EFBFBD><EFBFBD>day1<79><31>day2<79><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(day1-day2)<29><><EFBFBD><EFBFBD>
*
* @param day1
* @param day2
* @return
*/
public static int getIntervalYears(Date day1, Date day2) {
if (day1 == null || day2 == null) {
throw new IllegalArgumentException("Argument day1 or day2 must be not null.");
}
Calendar calDay1 = Calendar.getInstance();
calDay1.setTime(day1);
Calendar calDay2 = Calendar.getInstance();
calDay2.setTime(day2);
return calDay1.get(Calendar.YEAR) - calDay2.get(Calendar.YEAR);
}
private static long MILLISECOND_ONE_MINUTE = 60 * 1000;
private static long MILLISECOND_ONE_HOUR = 3600 * 1000;
private static long MILLISECOND_ONE_DAY = MILLISECOND_ONE_HOUR * 24;
/**
* <20><>ʽ<EFBFBD><CABD>(**<2A><>**Сʱ**<2A><>**<2A><>**<2A><><EFBFBD><EFBFBD>)<29><>ʾstart<72><74>end<6E><64>ʱ<EFBFBD><CAB1><EFBFBD>(end-start)
*
* @param start
* @param end
* @return
*/
public static String intervalFormatDisplay(Date start, Date end) {
long minus = getIntervalMilliSeconds(end, start);
if (minus < 0) {
throw new IllegalArgumentException("The date end must great than or equal the date start.");
}
StringBuilder interval = new StringBuilder();
long days = minus / MILLISECOND_ONE_DAY;
if (days > 0) {
interval.append(days).append("<EFBFBD><EFBFBD>");
}
minus -= days * MILLISECOND_ONE_DAY;
long hours = minus / MILLISECOND_ONE_HOUR;
if (hours > 0) {
interval.append(hours).append("Сʱ");
}
minus -= hours * MILLISECOND_ONE_HOUR;
long minutes = minus / MILLISECOND_ONE_MINUTE;
if (minutes > 0) {
interval.append(minutes).append("<EFBFBD><EFBFBD>");
}
minus -= minutes * MILLISECOND_ONE_MINUTE;
long seconds = minus / 1000;
if (seconds > 0) {
interval.append(seconds).append("<EFBFBD><EFBFBD>");
}
long millis = minus - seconds * 1000;
if (millis > 0) {
interval.append(millis).append("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
}
return interval.toString();
}
/**
* <20><><EFBFBD><EFBFBD>day1<79><31>day2ʱ<32><CAB1><EFBFBD><EFBFBD><EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD><EFBFBD><EFBFBD>(day1-day2)
*
* @param day1
* @param day2
* @return
*/
public static long getIntervalMilliSeconds(Date day1, Date day2) {
if (day1 == null || day2 == null) {
throw new IllegalArgumentException("Argument day1 or day2 must be not null.");
}
return day1.getTime()-day2.getTime();
}
public static String toUtc(java.util.Date date){
DateTime datetime=new DateTime(date, ISOChronology.getInstanceUTC());
return datetime.toString();
}
public static String toUtc(DateTime dateTime){
return dateTime.toString();
}
public static String toUtc(String date){
DateTime datetime=new DateTime(date, ISOChronology.getInstanceUTC());
return datetime.toString();
}
public static DateTime toUtcDate(String date){
DateTime datetime=new DateTime(date, ISOChronology.getInstanceUTC());
return datetime;
}
public static String toUtcLocal(java.util.Date date){
DateTime datetime=new DateTime(date,ISOChronology.getInstance());
return datetime.toString();
}
public static String toUtcLocal(String date){
DateTime datetime=new DateTime(date,ISOChronology.getInstance());
return datetime.toString();
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.util;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.logging.LogFactory;
/**
* @author Crystal
*
*/
public class DynaBean {
HashMap<String,Object> beanMap;
/**
*
*/
public DynaBean() {
beanMap=new HashMap<String,Object>();
}
/**
*
*/
public DynaBean(Map<String, Object> map) {
beanMap=new HashMap<String,Object>();
mapToDynaBean(map);
}
public void set(String name,Object value){
beanMap.put(name, value);
}
public Object get(String name){
return beanMap.get(name);
}
public void remove(String name){
beanMap.remove(name);
}
public void displayValues(){
Iterator<?> beanMapit = beanMap.entrySet().iterator();
int i=1;
LogFactory.getLog(DynaBean.class).debug("displayValues() *******************************************");
while (beanMapit.hasNext()) {
Map.Entry entry = (Map.Entry) beanMapit.next();
String fieldName = entry.getKey().toString();
LogFactory.getLog(DynaBean.class).debug("displayValues() Field "+(i++)+" "+fieldName+" : "+beanMap.get(fieldName));
}
LogFactory.getLog(DynaBean.class).debug("displayValues() *******************************************");
}
public <T> Object convertToBean(T bean){
return BeanConvert.map2Bean((T)bean, beanMap);
}
@SuppressWarnings("unchecked")
public <T> Object createBean(T cls){
T bean=(T)Instance.newInstance((Class<?>)cls);
return BeanConvert.map2Bean(bean, beanMap);
}
public Map<String, Object> toMap(){
return beanMap;
}
public DynaBean mapToDynaBean(Map<String, Object> map){
if(map.getClass().getName()=="java.util.HashMap"){
beanMap=(HashMap<String, Object>)map;
}else{
Iterator<?> mapIt = map.entrySet().iterator();
int i=1;
while (mapIt.hasNext()) {
Map.Entry entry = (Map.Entry) mapIt.next();
String fieldName = entry.getKey().toString();
beanMap.put(fieldName, map.get(fieldName));
LogFactory.getLog(DynaBean.class).debug("mapToDynaBean() Field "+(i++)+" "+fieldName+" : "+beanMap.get(fieldName));
}
}
return this;
}
}

View File

@@ -0,0 +1,519 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.util;
import java.io.IOException;
import java.io.Serializable;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.security.SecureRandom;
import java.util.Enumeration;
import java.util.Random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EthernetAddress
implements Serializable, Cloneable, Comparable<EthernetAddress>
{
private static final Logger _logger = LoggerFactory.getLogger(EthernetAddress.class);
private static final long serialVersionUID = 1L;
private final static char[] HEX_CHARS = "0123456789abcdefABCDEF".toCharArray();
/**
* We may need a random number generator, for creating dummy ethernet
* address if no real interface is found.
*/
protected static Random _rnd;
/**
* 48-bit MAC address, stored in 6 lowest-significant bytes (in
* big endian notation)
*/
protected final long _address;
/**
* Lazily-constructed String serialization
*/
private volatile String _asString;
/*
/**********************************************************************
/* Instance construction
/**********************************************************************
*/
/**
* String constructor; given a 'standard' ethernet MAC address string
* (like '00:C0:F0:3D:5B:7C'), constructs an EthernetAddress instance.
*
* Note that string is case-insensitive, and also that leading zeroes
* may be omitted. Thus '00:C0:F0:3D:5B:7C' and '0:c0:f0:3d:5b:7c' are
* equivalent, and a 'null' address could be passed as ':::::' as well
* as '00:00:00:00:00:00' (or any other intermediate combination).
*
* @param addrStr String representation of the ethernet address
*/
public EthernetAddress(String addrStr)
throws NumberFormatException
{
int len = addrStr.length();
long addr = 0L;
/* Ugh. Although the most logical format would be the 17-char one
* (12 hex digits separated by colons), apparently leading zeroes
* can be omitted. Thus... Can't just check string length. :-/
*/
for (int i = 0, j = 0; j < 6; ++j) {
if (i >= len) {
// Is valid if this would have been the last byte:
if (j == 5) {
addr <<= 8;
break;
}
throw new NumberFormatException("Incomplete ethernet address (missing one or more digits");
}
char c = addrStr.charAt(i);
++i;
int value;
// The whole number may be omitted (if it was zero):
if (c == ':') {
value = 0;
} else {
// No, got at least one digit?
if (c >= '0' && c <= '9') {
value = (c - '0');
} else if (c >= 'a' && c <= 'f') {
value = (c - 'a' + 10);
} else if (c >= 'A' && c <= 'F') {
value = (c - 'A' + 10);
} else {
throw new NumberFormatException("Non-hex character '"+c+"'");
}
// How about another one?
if (i < len) {
c = addrStr.charAt(i);
++i;
if (c != ':') {
value = (value << 4);
if (c >= '0' && c <= '9') {
value |= (c - '0');
} else if (c >= 'a' && c <= 'f') {
value |= (c - 'a' + 10);
} else if (c >= 'A' && c <= 'F') {
value |= (c - 'A' + 10);
} else {
throw new NumberFormatException("Non-hex character '"+c+"'");
}
}
}
}
addr = (addr << 8) | value;
if (c != ':') {
if (i < len) {
if (addrStr.charAt(i) != ':') {
throw new NumberFormatException("Expected ':', got ('"+ addrStr.charAt(i)+"')");
}
++i;
} else if (j < 5) {
throw new NumberFormatException("Incomplete ethernet address (missing one or more digits");
}
}
}
_address = addr;
}
/**
* Binary constructor that constructs an instance given the 6 byte
* (48-bit) address. Useful if an address is saved in binary format
* (for saving space for example).
*/
public EthernetAddress(byte [] addr)
throws NumberFormatException
{
if (addr.length != 6) {
throw new NumberFormatException("Ethernet address has to consist of 6 bytes");
}
long l = addr[0] & 0xFF;
for (int i = 1; i < 6; ++i) {
l = (l << 8) | (addr[i] & 0xFF);
}
_address = l;
}
/**
* Another binary constructor; constructs an instance from the given
* long argument; the lowest 6 bytes contain the address.
*
* @param addr long that contains the MAC address in 6 least significant
* bytes.
*/
public EthernetAddress(long addr) {
_address = addr;
}
/**
* Default cloning behaviour (bitwise copy) is just fine...
*/
public Object clone()
{
return new EthernetAddress(_address);
}
/**
* Constructs a new EthernetAddress given the byte array that contains
* binary representation of the address.
*
* Note that calling this method returns the same result as would
* using the matching constructor.
*
* @param addr Binary representation of the ethernet address
*
* @throws NumberFormatException if addr is invalid (less or more than
* 6 bytes in array)
*/
public static EthernetAddress valueOf(byte[] addr)
throws NumberFormatException
{
return new EthernetAddress(addr);
}
/**
* Constructs a new EthernetAddress given the byte array that contains
* binary representation of the address.
*
* Note that calling this method returns the same result as would
* using the matching constructor.
*
* @param addr Binary representation of the ethernet address
*
* @throws NumberFormatException if addr is invalid (less or more than
* 6 ints in array)
*/
public static EthernetAddress valueOf(int[] addr)
throws NumberFormatException
{
byte[] bAddr = new byte[addr.length];
for (int i = 0; i < addr.length; ++i) {
bAddr[i] = (byte) addr[i];
}
return new EthernetAddress(bAddr);
}
/**
* Constructs a new EthernetAddress given a string representation of
* the ethernet address.
*
* Note that calling this method returns the same result as would
* using the matching constructor.
*
* @param addrStr String representation of the ethernet address
*
* @throws NumberFormatException if addr representation is invalid
*/
public static EthernetAddress valueOf(String addrStr)
throws NumberFormatException
{
return new EthernetAddress(addrStr);
}
/**
* Constructs a new EthernetAddress given the long int value (64-bit)
* representation of the ethernet address (of which 48 LSB contain
* the definition)
*
* Note that calling this method returns the same result as would
* using the matching constructor.
*
* @param addr Long int representation of the ethernet address
*/
public static EthernetAddress valueOf(long addr)
{
return new EthernetAddress(addr);
}
/**
* Factory method that locates a network interface that has
* a suitable mac address (ethernet cards, and things that
* emulate one), and return that address. If there are multiple
* applicable interfaces, one of them is returned; which one
* is returned is not specified.
* Method is meant for accessing an address needed to construct
* generator for time+location based UUID generation method.
*
* @return Ethernet address of one of interfaces system has;
* not including local or loopback addresses; if one exists,
* null if no such interfaces are found.
*/
public static EthernetAddress fromInterface()
{
try {
Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
while (en.hasMoreElements()) {
NetworkInterface nint = en.nextElement();
if (!nint.isLoopback()) {
byte[] data = nint.getHardwareAddress();
if (data != null && data.length == 6) {
return new EthernetAddress(data);
}
}
}
} catch (java.net.SocketException e) {
// fine, let's take is as signal of not having any interfaces
}
return null;
}
/**
* Factory method that can be used to construct a random multicast
* address; to be used in cases where there is no "real" ethernet
* address to use. Address to generate should be a multicase address
* to avoid accidental collision with real manufacturer-assigned
* MAC addresses.
*<p>
* Internally a {@link SecureRandom} instance is used for generating
* random number to base address on.
*/
public static EthernetAddress constructMulticastAddress()
{
return constructMulticastAddress(_randomNumberGenerator());
}
/**
* Factory method that can be used to construct a random multicast
* address; to be used in cases where there is no "real" ethernet
* address to use. Address to generate should be a multicase address
* to avoid accidental collision with real manufacturer-assigned
* MAC addresses.
*<p>
* Address is created using specified random number generator.
*/
public static EthernetAddress constructMulticastAddress(Random rnd)
{
byte[] dummy = new byte[6];
synchronized (rnd) {
rnd.nextBytes(dummy);
}
/* Need to set the broadcast bit to indicate it's not a real
* address.
*/
/* 20-May-2010, tatu: Actually, we could use both second least-sig-bit
* ("locally administered") or the LSB (multicast), as neither is
* ever set for 'real' addresses.
* Since UUID specs recommends latter, use that.
*/
dummy[0] |= (byte) 0x01;
return new EthernetAddress(dummy);
}
/*
/**********************************************************************
/* Conversions to raw types
/**********************************************************************
*/
/**
* Returns 6 byte byte array that contains the binary representation
* of this ethernet address; byte 0 is the most significant byte
* (and so forth)
*
* @return 6 byte byte array that contains the binary representation
*/
public byte[] asByteArray()
{
byte[] result = new byte[6];
toByteArray(result);
return result;
}
/**
* Synonym to 'asByteArray()'
*
* @return 6 byte byte array that contains the binary representation
*/
public byte[] toByteArray() { return asByteArray(); }
public void toByteArray(byte[] array) {
if (array.length < 6) {
throw new IllegalArgumentException("Too small array, need to have space for 6 bytes");
}
toByteArray(array, 0);
}
public void toByteArray(byte[] array, int pos)
{
if (pos < 0 || (pos + 6) > array.length) {
throw new IllegalArgumentException("Illegal offset ("+pos+"), need room for 6 bytes");
}
int i = (int) (_address >> 32);
array[pos++] = (byte) (i >> 8);
array[pos++] = (byte) i;
i = (int) _address;
array[pos++] = (byte) (i >> 24);
array[pos++] = (byte) (i >> 16);
array[pos++] = (byte) (i >> 8);
array[pos] = (byte) i;
}
public long toLong() {
return _address;
}
/*
/**********************************************************************
/* Accessors
/**********************************************************************
*/
/**
* Method that can be used to check if this address refers
* to a multicast address.
* Such addresses are never assigned to individual network
* cards.
*/
public boolean isMulticastAddress() {
return (((int) (_address >> 40)) & 0x01) != 0;
}
/**
* Method that can be used to check if this address refers
* to a "locally administered address"
* (see [http://en.wikipedia.org/wiki/MAC_address] for details).
* Such addresses are not assigned to individual network
* cards.
*/
public boolean isLocallyAdministeredAddress() {
return (((int) (_address >> 40)) & 0x02) != 0;
}
/*
/**********************************************************************
/* Standard methods
/**********************************************************************
*/
@Override
public boolean equals(Object o)
{
if (o == this) return true;
if (o == null) return false;
if (o.getClass() != getClass()) return false;
return ((EthernetAddress) o)._address == _address;
}
/**
* Method that compares this EthernetAddress to one passed in as
* argument. Comparison is done simply by comparing individual
* address bytes in the order.
*
* @return negative number if this EthernetAddress should be sorted before the
* parameter address if they are equal, os positive non-zero number if this address
* should be sorted after parameter
*/
public int compareTo(EthernetAddress other)
{
long l = _address - other._address;
if (l < 0L) return -1;
return (l == 0L) ? 0 : 1;
}
/**
* Returns the canonical string representation of this ethernet address.
* Canonical means that all characters are lower-case and string length
* is always 17 characters (ie. leading zeroes are not omitted).
*
* @return Canonical string representation of this ethernet address.
*/
@Override
public String toString()
{
String str = _asString;
if (str != null) {
return str;
}
/* Let's not cache the output here (unlike with UUID), assuming
* this won't be called as often:
*/
StringBuilder b = new StringBuilder(17);
int i1 = (int) (_address >> 32);
int i2 = (int) _address;
_appendHex(b, i1 >> 8);
b.append(':');
_appendHex(b, i1);
b.append(':');
_appendHex(b, i2 >> 24);
b.append(':');
_appendHex(b, i2 >> 16);
b.append(':');
_appendHex(b, i2 >> 8);
b.append(':');
_appendHex(b, i2);
_asString = str = b.toString();
return str;
}
/*
/**********************************************************************
/* Internal methods
/**********************************************************************
*/
/**
* Helper method for accessing configured random number generator
*/
protected synchronized static Random _randomNumberGenerator()
{
if (_rnd == null) {
_rnd = new SecureRandom();
}
return _rnd;
}
private final void _appendHex(StringBuilder sb, int hex)
{
sb.append(HEX_CHARS[(hex >> 4) & 0xF]);
sb.append(HEX_CHARS[(hex & 0x0f)]);
}
public boolean isPortAvailable(String host , int port) {
Socket socket = new Socket();
try {
socket.connect(new InetSocketAddress(host, port));
} catch (IOException e) {
_logger.debug("IOException",e);
return false;
} finally {
try {
socket.close();
} catch (IOException e) {
_logger.debug("IOException Close ",e);
}
}
return true;
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.util;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.regex.*;
public abstract class HttpEncoder {
private static final String CHARSET = "UTF-8";
private static final Map<String, String> ENCODING_RULES;
static {
final Map<String, String> rules = new HashMap<>();
rules.put("*", "%2A");
rules.put("+", "%20");
rules.put("%7E", "~");
ENCODING_RULES = Collections.unmodifiableMap(rules);
}
public static String encode(String plain) throws Exception {
String encoded;
try {
encoded = URLEncoder.encode(plain, CHARSET);
} catch (UnsupportedEncodingException uee) {
throw new Exception("Charset not found while encoding string: " + CHARSET, uee);
}
for (Map.Entry<String, String> rule : ENCODING_RULES.entrySet()) {
encoded = applyRule(encoded, rule.getKey(), rule.getValue());
}
return encoded;
}
private static String applyRule(String encoded, String toReplace, String replacement) {
return encoded.replaceAll(Pattern.quote(toReplace), replacement);
}
public static String decode(String encoded) throws UnsupportedEncodingException {
return URLDecoder.decode(encoded, CHARSET);
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.util;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
public class HttpsTrusts {
private static void trustAllHttpsCertificates() throws Exception {
javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
javax.net.ssl.TrustManager tm = new HttpsTrustsTM();
trustAllCerts[0] = tm;
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, null);
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
/*
* https ssl auto trust
*/
public static void beforeConnection() {
try {
trustAllHttpsCertificates();
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
return true;
}
});
} catch(Exception e) {
e.printStackTrace();
}
}
static class HttpsTrustsTM implements javax.net.ssl.TrustManager,javax.net.ssl.X509TrustManager {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
}
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.util;
import java.util.Date;
import org.slf4j.LoggerFactory;
/**
* 20位的流水号
* 8位系统日期YYYYMMDD+2位节点号+6位时间戳为HHMMSS+4位顺序流水号。
* 其中4位顺序流水号要求为“数值格式位数不足左补零各系统顺序生成”,为了避免顺序号重复4位流水为该秒内的顺序流水即每秒内每个节点最多1万笔交易
*
* @author Crystal.sea
*
*/
public class IdSequence {
public static String OLD_DATETIME="";
/**
* 静态属性
*/
public static int STATIC_SEQUENCE=0;
/**
* 默认节点
*/
public static String DEFAULT_NODE_NUMBER="01";
public static String STATIC_NODE_NUMBER="--";
/**
* 生成20位的流水号
* @return 流水号
*/
public static synchronized String next(){
String currentDateTime=getCurrentSystemDateTime();
if(null==currentDateTime){
LoggerFactory.getLogger(IdSequence.class).error("获取系统日期失败");
return null;
}
StringBuffer sequenceNumber=new StringBuffer();
sequenceNumber.append(currentDateTime.substring(0, 8));
sequenceNumber.append(getNodeNumber());
sequenceNumber.append(currentDateTime.substring(8));
sequenceNumber.append(nextSequence());
return sequenceNumber.toString();
}
public static final String initNodeNumber(String nodeNumbers){
if(STATIC_NODE_NUMBER.equals("--")){
if(null!=nodeNumbers&&!nodeNumbers.equals("")){
String ipAddressConfigValue=nodeNumbers;
LoggerFactory.getLogger(IdSequence.class).info("ARE config.node.number : "+ipAddressConfigValue);
if(ipAddressConfigValue.indexOf(",")>-1){
String hostIpAddress=MacAddress.getAllHostMacAddress();//获得本机IP
LoggerFactory.getLogger(IdSequence.class).info("hostIpAddress : "+hostIpAddress);
String []ipAddressValues=ipAddressConfigValue.split(",");
for(String ipvalue : ipAddressValues){
String[] ipNode=ipvalue.split("=");
if(ipNode!=null&&ipNode.length>0&&hostIpAddress.indexOf(ipNode[0])>-1){
STATIC_NODE_NUMBER=ipNode[1];
}
}
if(STATIC_NODE_NUMBER.equals("--")){
LoggerFactory.getLogger(IdSequence.class).error("GET MAC BIND NODE ERROR . ");
STATIC_NODE_NUMBER=DEFAULT_NODE_NUMBER;
}
}else{
STATIC_NODE_NUMBER=nodeNumbers;
}
LoggerFactory.getLogger(IdSequence.class).info("STATIC_NODE_SEQUENCE_NUMBER : "+STATIC_NODE_NUMBER);
if(STATIC_NODE_NUMBER.length()!=2){
LoggerFactory.getLogger(IdSequence.class).error("系统节点号必须2位");
}
}else{
STATIC_NODE_NUMBER=DEFAULT_NODE_NUMBER;
}
}
return STATIC_NODE_NUMBER;
}
public static final String getNodeNumber(){
return STATIC_NODE_NUMBER;
}
/**
* 同一时刻只有一个访问
* @return
*/
private static final synchronized String nextSequence(){
STATIC_SEQUENCE=(STATIC_SEQUENCE+1)%10000;
return String.format("%04d", STATIC_SEQUENCE);
}
/**
* 获取系统当前日期格式为yyyyMMddHHmmSS
* @return 当前系统日期
*/
private static synchronized String getCurrentSystemDateTime(){
String currentdatetime=null;
synchronized(OLD_DATETIME)
{
currentdatetime=(new java.text.SimpleDateFormat("yyyyMMddHHmmss")).format(new Date());
/**
* 判断是否是新的时间如果是新时间则STATIC_SEQUENCE从0开始计数
*/
if(!currentdatetime.equals(OLD_DATETIME)){
STATIC_SEQUENCE=0;
OLD_DATETIME=currentdatetime;
}
}
return currentdatetime;
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.util;
import java.lang.reflect.Constructor;
/**
* @author Crystal
*
*/
public class Instance {
/**
*
*/
public Instance() {
}
public static Object newInstance(String className) {
Class<?> cls;
try {
cls = Class.forName(className);
Constructor<?> constructor = cls.getConstructor();
return constructor.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Object newInstance(Class<?> cls) {
try {
Constructor<?> constructor = cls.getConstructor();
return constructor.newInstance();
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Object newInstance(String className, Object[] args) {
Class<?> newClass;
try {
newClass = Class.forName(className);
Class[] argsClass = new Class[args.length];
for (int i = 0, j = args.length; i < j; i++) {
argsClass[i] = args[i].getClass();
}
Constructor<?> cons = newClass.getConstructor(argsClass);
return cons.newInstance(args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static <T> Object newInstance(Class<T> cls, Object[] args) {
try {
Class[] argsClass = new Class[args.length];
for (int i = 0, j = args.length; i < j; i++) {
argsClass[i] = args[i].getClass();
}
Constructor<T> cons = cls.getConstructor(argsClass);
return cons.newInstance(args);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

View File

@@ -0,0 +1,118 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.util;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import java.io.IOException;
public class JsonUtils {
/**
* Transform json string to java bean object.
*
* @param json String
* @param bean Object
* @return Object
*/
public static Object json2Object(String json, Object bean) {
try {
bean = (new ObjectMapper()).readValue(json, bean.getClass());
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bean;
}
/**
* Transform json string to java bean object.
*
* @param json String
* @param cls Class
* @return Object
*/
public static <T> T json2Object(String json, Class<T> cls) {
T bean = null;
try {
bean = (new ObjectMapper()).readValue(json, cls);
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bean;
}
/**
* Transform java bean object to json string.
*
* @param bean Object
* @return string
*/
public static String object2Json(Object bean) {
String json = "";
try {
json = (new ObjectMapper()).writeValueAsString(bean);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return json;
}
/**
* Transform json string to java bean object use Gson.
*
* @param <T> Class
* @param json String
* @return Object
*/
public static <T> T gson2Object(String json, Class<T> cls) {
T newBean = (new Gson()).fromJson(json, cls);
return newBean;
}
/**
* Transform java bean object to json string use Gson.
*
* @param bean Object
* @return string
*/
public static String gson2Json(Object bean) {
String json = "";
// convert java object to JSON format,
// and returned as JSON formatted string
json = (new Gson()).toJson(bean);
return json;
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.util;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.Properties;
import org.slf4j.LoggerFactory;
/**
* @author Crystal.Sea
*
*/
public class MacAddress {
public static String os;
static{
Properties prop = System.getProperties();
os = prop.getProperty("os.name");
LoggerFactory.getLogger(MacAddress.class).info("OS : "+os);
}
public static String getAllHostMacAddress(){
String hostIpAddress="";
try {
Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
InetAddress inetAddress = null;
while (netInterfaces.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();
if(ni.getInetAddresses().hasMoreElements()){
inetAddress = (InetAddress) ni.getInetAddresses().nextElement();
if(!inetAddress.isLoopbackAddress()){
hostIpAddress += getMac(inetAddress)+",";
LoggerFactory.getLogger(MacAddress.class).info("host MAC : "+getMac(inetAddress));
}
}
}
} catch (SocketException e) {
e.printStackTrace();
}
return hostIpAddress;
}
public static String getMac(InetAddress ia) throws SocketException {
//获取网卡,获取地址
byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
//LoggerFactory.getLogger(MacAddress.class).info("mac数组长度"+mac.length);
StringBuffer sb = new StringBuffer("");
for(int i=0; i<mac.length; i++) {
if(i!=0) {
if(os.startsWith("win") || os.startsWith("Win") ){
sb.append("-");//win
}else{
sb.append(":");//linux
}
}
//字节转换为整数
int temp = mac[i]&0xff;
String str = Integer.toHexString(temp);
if(str.length()==1) {
sb.append("0"+str);
}else {
sb.append(str);
}
}
return sb.toString().toUpperCase();
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
*/
package org.maxkey.util;
import java.lang.reflect.Method;
/**
* @author Crystal
*
*/
public class MethodInvoke {
/**
*
*/
public MethodInvoke() {
}
public static Object invokeMethod(Object bean, String methodName,
Object[] args) throws Exception {
Class<? extends Object> beanClass = bean.getClass();
Class[] argsClass = new Class[args.length];
for (int i = 0, j = args.length; i < j; i++) {
argsClass[i] = args[i].getClass();
//LogFactory.getLog(MethodInvoke.class).debug("invokeMethod args : "+args[i]+" argsClass:"+argsClass[i]);
}
Method method = beanClass.getMethod(methodName, argsClass);
//LogFactory.getLog(MethodInvoke.class).debug("invokeMethod methodName:"+methodName);
return method.invoke(bean, args);
}
public static Object invokeMethod(Object bean, String methodName)
throws Exception {
Class<? extends Object> beanClass = bean.getClass();
Method method = beanClass.getMethod(methodName);
//LogFactory.getLog(MethodInvoke.class).debug("invokeMethod methodName:"+methodName);
return method.invoke(bean, new Object[] {});
}
public static Object invokeStaticMethod(Class<?> beanClass, String methodName,
Object[] args) throws Exception {
Class[] argsClass = new Class[args.length];
for (int i = 0, j = args.length; i < j; i++) {
argsClass[i] = args[i].getClass();
//LogFactory.getLog(MethodInvoke.class).debug("invokeStaticMethod args : "+args[i]+" argsClass:"+argsClass[i]);
}
Method method = beanClass.getMethod(methodName, argsClass);
//LogFactory.getLog(MethodInvoke.class).debug("invokeStaticMethod methodName:"+methodName);
return method.invoke(null, args);
}
public static Object invokeStaticMethod(Class<?> beanClass, String methodName)
throws Exception {
Method method = beanClass.getMethod(methodName);
//LogFactory.getLog(MethodInvoke.class).debug("invokeStaticMethod methodName:"+methodName);
return method.invoke(null, new Object[] {});
}
}

Some files were not shown because too many files have changed in this diff Show More