separate common
This commit is contained in:
3
maxkey-common/src/main/java/META-INF/MANIFEST.MF
Normal file
3
maxkey-common/src/main/java/META-INF/MANIFEST.MF
Normal file
@@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
Class-Path:
|
||||
|
||||
84
maxkey-common/src/main/java/org/maxkey/cache/AbstractCache.java
vendored
Normal file
84
maxkey-common/src/main/java/org/maxkey/cache/AbstractCache.java
vendored
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
63
maxkey-common/src/main/java/org/maxkey/cache/CacheFactory.java
vendored
Normal file
63
maxkey-common/src/main/java/org/maxkey/cache/CacheFactory.java
vendored
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
25
maxkey-common/src/main/java/org/maxkey/cache/package-info.java
vendored
Normal file
25
maxkey-common/src/main/java/org/maxkey/cache/package-info.java
vendored
Normal 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;
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
147
maxkey-common/src/main/java/org/maxkey/crypto/Base64Utils.java
Normal file
147
maxkey-common/src/main/java/org/maxkey/crypto/Base64Utils.java
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
141
maxkey-common/src/main/java/org/maxkey/crypto/DigestUtils.java
Normal file
141
maxkey-common/src/main/java/org/maxkey/crypto/DigestUtils.java
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
80
maxkey-common/src/main/java/org/maxkey/crypto/HexUtils.java
Normal file
80
maxkey-common/src/main/java/org/maxkey/crypto/HexUtils.java
Normal 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());
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
246
maxkey-common/src/main/java/org/maxkey/crypto/KeyPairUtil.java
Normal file
246
maxkey-common/src/main/java/org/maxkey/crypto/KeyPairUtil.java
Normal 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;
|
||||
}
|
||||
}
|
||||
75
maxkey-common/src/main/java/org/maxkey/crypto/Md5Sum.java
Normal file
75
maxkey-common/src/main/java/org/maxkey/crypto/Md5Sum.java
Normal 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;
|
||||
}
|
||||
}
|
||||
177
maxkey-common/src/main/java/org/maxkey/crypto/RSAUtils.java
Normal file
177
maxkey-common/src/main/java/org/maxkey/crypto/RSAUtils.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
79
maxkey-common/src/main/java/org/maxkey/crypto/SM3.java
Normal file
79
maxkey-common/src/main/java/org/maxkey/crypto/SM3.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
206
maxkey-common/src/main/java/org/maxkey/crypto/cert/NetUtil.java
Normal file
206
maxkey-common/src/main/java/org/maxkey/crypto/cert/NetUtil.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
* < 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
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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 + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
*/
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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(); }
|
||||
*
|
||||
* }
|
||||
*/
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
201
maxkey-common/src/main/java/org/maxkey/crypto/password/Md4.java
Normal file
201
maxkey-common/src/main/java/org/maxkey/crypto/password/Md4.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
24
maxkey-common/src/main/java/org/maxkey/pretty/Pretty.java
Normal file
24
maxkey-common/src/main/java/org/maxkey/pretty/Pretty.java
Normal 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);
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
127
maxkey-common/src/main/java/org/maxkey/util/BeanConvert.java
Normal file
127
maxkey-common/src/main/java/org/maxkey/util/BeanConvert.java
Normal 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;
|
||||
}
|
||||
}
|
||||
335
maxkey-common/src/main/java/org/maxkey/util/BeanUtil.java
Normal file
335
maxkey-common/src/main/java/org/maxkey/util/BeanUtil.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
660
maxkey-common/src/main/java/org/maxkey/util/DateUtils.java
Normal file
660
maxkey-common/src/main/java/org/maxkey/util/DateUtils.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
104
maxkey-common/src/main/java/org/maxkey/util/DynaBean.java
Normal file
104
maxkey-common/src/main/java/org/maxkey/util/DynaBean.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
519
maxkey-common/src/main/java/org/maxkey/util/EthernetAddress.java
Normal file
519
maxkey-common/src/main/java/org/maxkey/util/EthernetAddress.java
Normal 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;
|
||||
}
|
||||
}
|
||||
59
maxkey-common/src/main/java/org/maxkey/util/HttpEncoder.java
Normal file
59
maxkey-common/src/main/java/org/maxkey/util/HttpEncoder.java
Normal 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);
|
||||
|
||||
}
|
||||
}
|
||||
75
maxkey-common/src/main/java/org/maxkey/util/HttpsTrusts.java
Normal file
75
maxkey-common/src/main/java/org/maxkey/util/HttpsTrusts.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
140
maxkey-common/src/main/java/org/maxkey/util/IdSequence.java
Normal file
140
maxkey-common/src/main/java/org/maxkey/util/IdSequence.java
Normal 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;
|
||||
}
|
||||
}
|
||||
97
maxkey-common/src/main/java/org/maxkey/util/Instance.java
Normal file
97
maxkey-common/src/main/java/org/maxkey/util/Instance.java
Normal 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;
|
||||
|
||||
}
|
||||
}
|
||||
118
maxkey-common/src/main/java/org/maxkey/util/JsonUtils.java
Normal file
118
maxkey-common/src/main/java/org/maxkey/util/JsonUtils.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
92
maxkey-common/src/main/java/org/maxkey/util/MacAddress.java
Normal file
92
maxkey-common/src/main/java/org/maxkey/util/MacAddress.java
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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
Reference in New Issue
Block a user