This commit is contained in:
付庆吉
2022-01-25 09:18:52 +08:00
parent 8fe63a1a25
commit 8c954e21f6
14 changed files with 17 additions and 2975 deletions

View File

@ -61,13 +61,14 @@ public class OperationLogServiceImpl implements OperationLogService {
operationLog.setMethod(element.getMethodName());
}
BaseCacheUser user = cacheUserService.getCacheUser();
operationLog.setUser(user);
if (null != user) {
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
// 提取token头信息 ;
operationLog.setToken(request.getHeader(AUTHORIZATION_HEADER))
.setUser(user)
.setUrl(request.getMethod() + "." + request.getRequestURI());
if (request != null) {
// 提取token头信息 ;
operationLog.setToken(request.getHeader(AUTHORIZATION_HEADER))
.setUrl(request.getMethod() + "." + request.getRequestURI());
}
}
operationLog.setId(PropertyUtils.getSnowflakeId())

View File

@ -1,5 +1,6 @@
package com.chinaunicom.mall.ebtp.common.util;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@ -27,7 +28,11 @@ public final class HttpContextUtils {
* @return HttpServletRequest
*/
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
return ((ServletRequestAttributes) requestAttributes).getRequest();
}
return null;
}
/**
@ -36,6 +41,10 @@ public final class HttpContextUtils {
* @return
*/
public static HttpServletResponse getHttpServletResponse() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
return ((ServletRequestAttributes) requestAttributes).getResponse();
}
return null;
}
}

View File

@ -1,33 +0,0 @@
/*
* Copyright 2016 DTCC, Fujitsu Australia Software Technology, IBM - All Rights Reserved.
*
* 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 com.chinaunicom.mall.ebtp.common.crypto.exception;
public class BaseException extends Exception {
private static final long serialVersionUID = 1L;
public BaseException(String message, Throwable parent) {
super(message, parent);
}
public BaseException(String message) {
super(message);
}
public BaseException(Throwable t) {
super(t);
}
}

View File

@ -1,29 +0,0 @@
/*
* Copyright 2016 DTCC, Fujitsu Australia Software Technology - All Rights Reserved.
*
* 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 com.chinaunicom.mall.ebtp.common.crypto.exception;
public class CryptoException extends BaseException {
private static final long serialVersionUID = 1L;
public CryptoException(String message, Exception parent) {
super(message, parent);
}
public CryptoException(String message) {
super(message);
}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2016 DTCC, Fujitsu Australia Software Technology - All Rights Reserved.
*
* 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 com.chinaunicom.mall.ebtp.common.crypto.exception;
/*
Exception that is thrown from Chaincode
*/
public class InvalidArgumentException extends BaseException {
private static final long serialVersionUID = -6094512275378074427L;
public InvalidArgumentException(String message, Exception parent) {
super(message, parent);
}
public InvalidArgumentException(String message) {
super(message);
}
public InvalidArgumentException(Throwable t) {
super(t);
}
}

View File

@ -1,606 +0,0 @@
/*
* Copyright 2016, 2017 IBM, DTCC, Fujitsu Australia Software Technology, IBM - All Rights Reserved.
*
* 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 com.chinaunicom.mall.ebtp.common.crypto.helper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import static java.lang.String.format;
/**
* Config allows for a global config of the toolkit. Central location for all
* toolkit configuration defaults. Has a local config file that can override any
* property defaults. Config file can be relocated via a system property
* "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.configuration". Any property can be overridden
* with environment variable and then overridden
* with a java system property. Property hierarchy goes System property
* overrides environment variable which overrides config file for default values specified here.
*/
public class Config {
private static final Log logger = LogFactory.getLog(Config.class);
private static final String DEFAULT_CONFIG = "config.properties";
public static final String ORG_HYPERLEDGER_FABRIC_SDK_CONFIGURATION = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.configuration";
private static final String DEFAULT_NULL = "\0DEFAULT_NULL\0".intern(); // Used to set value to NULL since null won't work.
/**
* Timeout settings
**/
public static final String PROPOSAL_WAIT_TIME = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.proposal.wait.time";
public static final String CHANNEL_CONFIG_WAIT_TIME = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.channelconfig.wait_time";
public static final String TRANSACTION_CLEANUP_UP_TIMEOUT_WAIT_TIME = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.client.transaction_cleanup_up_timeout_wait_time";
public static final String ORDERER_RETRY_WAIT_TIME = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.orderer_retry.wait_time";
public static final String ORDERER_WAIT_TIME = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.orderer.ordererWaitTimeMilliSecs";
public static final String PEER_EVENT_REGISTRATION_WAIT_TIME = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.peer.eventRegistration.wait_time";
public static final String PEER_EVENT_RETRY_WAIT_TIME = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.peer.retry_wait_time";
public static final String PEER_EVENT_RECONNECTION_WARNING_RATE = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.peer.reconnection_warning_rate";
public static final String GENESISBLOCK_WAIT_TIME = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.channel.genesisblock_wait_time";
/**
* Crypto configuration settings -- settings should not be changed.
**/
public static final String DEFAULT_CRYPTO_SUITE_FACTORY = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.crypto.default_crypto_suite_factory";
public static final String SECURITY_LEVEL = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.security_level";
public static final String SECURITY_PROVIDER_CLASS_NAME = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.security_provider_class_name";
public static final String SECURITY_CURVE_MAPPING = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.security_curve_mapping";
public static final String HASH_ALGORITHM = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.hash_algorithm";
public static final String ASYMMETRIC_KEY_TYPE = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.crypto.asymmetric_key_type";
public static final String CERTIFICATE_FORMAT = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.crypto.certificate_format";
public static final String SIGNATURE_ALGORITHM = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.crypto.default_signature_algorithm";
/**
* Logging settings
**/
public static final String MAX_LOG_STRING_LENGTH = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.log.stringlengthmax";
public static final String EXTRALOGLEVEL = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.log.extraloglevel"; // ORG_HYPERLEDGER_FABRIC_SDK_LOG_EXTRALOGLEVEL
public static final String LOGGERLEVEL = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.loglevel"; // ORG_HYPERLEDGER_FABRIC_SDK_LOGLEVEL=TRACE,DEBUG
public static final String DIAGNOTISTIC_FILE_DIRECTORY = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.diagnosticFileDir"; //ORG_HYPERLEDGER_FABRIC_SDK_DIAGNOSTICFILEDIR
/**
* Connections settings
*/
public static final String CONN_SSL_PROVIDER = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.connections.ssl.sslProvider";
public static final String CONN_SSL_NEGTYPE = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.connections.ssl.negotiationType";
/**
* Default HFClient thread executor settings.
*/
public static final String CLIENT_THREAD_EXECUTOR_COREPOOLSIZE = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.client.thread_executor_corepoolsize";
public static final String CLIENT_THREAD_EXECUTOR_MAXIMUMPOOLSIZE = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.client.thread_executor_maximumpoolsize";
public static final String CLIENT_THREAD_EXECUTOR_KEEPALIVETIME = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.client.thread_executor_keepalivetime";
public static final String CLIENT_THREAD_EXECUTOR_KEEPALIVETIMEUNIT = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.client.thread_executor_keepalivetimeunit";
/**
* Miscellaneous settings
**/
public static final String PROPOSAL_CONSISTENCY_VALIDATION = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.proposal.consistency_validation";
public static final String SERVICE_DISCOVER_FREQ_SECONDS = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.service_discovery.frequency_sec";
public static final String SERVICE_DISCOVER_WAIT_TIME = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.service_discovery.discovery_wait_time";
public static final String SERVICE_DISCOVER_AS_LOCALHOST = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.service_discovery.as_localhost";
public static final String LIFECYCLE_CHAINCODE_ENDORSEMENT_PLUGIN = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.lifecycle.chaincode_endorsement_plugin"; //ORG_HYPERLEDGER_FABRIC_SDK_LIFECYCLE_CHAINCODE_ENDORSEMENT_PLUGIN
public static final String LIFECYCLE_CHAINCODE_VALIDATION_PLUGIN = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.lifecycle.chaincode_validation_plugin"; //ORG_HYPERLEDGER_FABRIC_SDK_LIFECYCLE_CHAINCODE_VALIDATION_PLUGIN
public static final String LIFECYCLE_INITREQUIREDDEFAULT = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.lifecycle.initRequiredDefault"; //ORG_HYPERLEDGER_FABRIC_SDK_LIFECYCLE_INITREQUIREDDEFAULT
private static Config config;
private static final Properties sdkProperties = new Properties();
private static final AtomicLong count = new AtomicLong(0);
//Provides a unique id for logging to identify a specific instance.
public String getNextID() {
return "" + count.incrementAndGet();
}
private Config() {
File loadFile;
FileInputStream configProps;
try {
loadFile = new File(System.getProperty(ORG_HYPERLEDGER_FABRIC_SDK_CONFIGURATION, DEFAULT_CONFIG))
.getAbsoluteFile();
logger.debug(format("Loading configuration from %s and it is present: %b", loadFile.toString(),
loadFile.exists()));
configProps = new FileInputStream(loadFile);
sdkProperties.load(configProps);
} catch (IOException e) {
logger.warn(format("Failed to load any configuration from: %s. Using toolkit defaults",
DEFAULT_CONFIG));
} finally {
// Default values
/**
* Timeout settings
**/
defaultProperty(PROPOSAL_WAIT_TIME, "120000");
defaultProperty(CHANNEL_CONFIG_WAIT_TIME, "15000");
defaultProperty(ORDERER_RETRY_WAIT_TIME, "200");
defaultProperty(ORDERER_WAIT_TIME, "10000");
defaultProperty(PEER_EVENT_REGISTRATION_WAIT_TIME, "5000");
defaultProperty(PEER_EVENT_RETRY_WAIT_TIME, "500");
defaultProperty(GENESISBLOCK_WAIT_TIME, "5000");
/**
* This will NOT complete any transaction futures time out and must be kept WELL above any expected future timeout
* for transactions sent to the Orderer. For internal cleanup only.
*/
defaultProperty(TRANSACTION_CLEANUP_UP_TIMEOUT_WAIT_TIME, "600000"); //10 min.
/**
* Crypto configuration settings
**/
defaultProperty(DEFAULT_CRYPTO_SUITE_FACTORY, "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.security.HLSDKJCryptoSuiteFactory");
defaultProperty(SECURITY_LEVEL, "256");
defaultProperty(SECURITY_PROVIDER_CLASS_NAME, BouncyCastleProvider.class.getName());
defaultProperty(SECURITY_CURVE_MAPPING, "256=secp256r1:384=secp384r1");
defaultProperty(HASH_ALGORITHM, "SHA2");
defaultProperty(ASYMMETRIC_KEY_TYPE, "EC");
defaultProperty(CERTIFICATE_FORMAT, "X.509");
defaultProperty(SIGNATURE_ALGORITHM, "SHA256withECDSA");
/**
* Connection defaults
*/
defaultProperty(CONN_SSL_PROVIDER, "openSSL");
defaultProperty(CONN_SSL_NEGTYPE, "TLS");
/**
* Default HFClient thread executor settings.
*/
defaultProperty(CLIENT_THREAD_EXECUTOR_COREPOOLSIZE, "0");
defaultProperty(CLIENT_THREAD_EXECUTOR_MAXIMUMPOOLSIZE, "" + Integer.MAX_VALUE);
defaultProperty(CLIENT_THREAD_EXECUTOR_KEEPALIVETIME, "" + "60");
defaultProperty(CLIENT_THREAD_EXECUTOR_KEEPALIVETIMEUNIT, "SECONDS");
/**
* Logging settings
**/
defaultProperty(MAX_LOG_STRING_LENGTH, "64");
defaultProperty(EXTRALOGLEVEL, "0");
defaultProperty(LOGGERLEVEL, null);
defaultProperty(DIAGNOTISTIC_FILE_DIRECTORY, null);
/**
* Miscellaneous settings
*/
defaultProperty(PROPOSAL_CONSISTENCY_VALIDATION, "true");
defaultProperty(PEER_EVENT_RECONNECTION_WARNING_RATE, "50");
defaultProperty(SERVICE_DISCOVER_FREQ_SECONDS, "120");
defaultProperty(SERVICE_DISCOVER_WAIT_TIME, "5000");
defaultProperty(SERVICE_DISCOVER_AS_LOCALHOST, "false");
defaultProperty(LIFECYCLE_CHAINCODE_ENDORSEMENT_PLUGIN, DEFAULT_NULL);
defaultProperty(LIFECYCLE_CHAINCODE_VALIDATION_PLUGIN, DEFAULT_NULL);
defaultProperty(LIFECYCLE_INITREQUIREDDEFAULT, DEFAULT_NULL);
final String inLogLevel = sdkProperties.getProperty(LOGGERLEVEL);
if (null != inLogLevel) {
}
}
}
/**
* getConfig return back singleton for SDK configuration.
*
* @return Global configuration
*/
public static Config getConfig() {
if (null == config) {
config = new Config();
}
return config;
}
/**
* getProperty return back property for the given value.
*
* @param property
* @return String value for the property
*/
private String getProperty(String property) {
if (!sdkProperties.containsKey(property)) {
logger.warn(format("No configuration value found for '%s'", property));
}
String ret = sdkProperties.getProperty(property);
if (DEFAULT_NULL.equals(ret)) {
ret = null;
}
return ret;
}
private static void defaultProperty(String key, String value) {
String ret = System.getProperty(key);
if (ret != null) {
sdkProperties.put(key, ret);
} else {
String envKey = key.toUpperCase().replaceAll("\\.", "_");
ret = System.getenv(envKey);
if (null != ret) {
sdkProperties.put(key, ret);
} else {
if (null == sdkProperties.getProperty(key) && value != null) {
sdkProperties.put(key, value);
}
}
}
}
/**
* Get the configured security level. The value determines the elliptic curve used to generate keys.
*
* @return the security level.
*/
public int getSecurityLevel() {
return Integer.parseInt(getProperty(SECURITY_LEVEL));
}
/**
* Get the configured security provider.
* This is the security provider used for the default SDK crypto suite factory.
*
* @return the security provider.
*/
public String getSecurityProviderClassName() {
return getProperty(SECURITY_PROVIDER_CLASS_NAME);
}
/**
* Get the name of the configured hash algorithm, used for digital signatures.
*
* @return the hash algorithm name.
*/
public String getHashAlgorithm() {
return getProperty(HASH_ALGORITHM);
}
/**
* The default ssl provider for grpc connection
*
* @return The default ssl provider for grpc connection
*/
public String getDefaultSSLProvider() {
return getProperty(CONN_SSL_PROVIDER);
}
/**
* The default ssl negotiation type
*
* @return The default ssl negotiation type
*/
public String getDefaultSSLNegotiationType() {
return getProperty(CONN_SSL_NEGTYPE);
}
private Map<Integer, String> curveMapping = null;
/**
* Get a mapping from strength to curve desired.
*
* @return mapping from strength to curve name to use.
*/
public Map<Integer, String> getSecurityCurveMapping() {
if (curveMapping == null) {
curveMapping = parseSecurityCurveMappings(getProperty(SECURITY_CURVE_MAPPING));
}
return Collections.unmodifiableMap(curveMapping);
}
public static Map<Integer, String> parseSecurityCurveMappings(final String property) {
Map<Integer, String> lcurveMapping = new HashMap<>(8);
if (property != null && !property.isEmpty()) { //empty will be caught later.
String[] cmaps = property.split("[ \t]*:[ \t]*");
for (String mape : cmaps) {
String[] ep = mape.split("[ \t]*=[ \t]*");
if (ep.length != 2) {
logger.warn(format("Bad curve mapping for %s in property %s", mape, SECURITY_CURVE_MAPPING));
continue;
}
try {
int parseInt = Integer.parseInt(ep[0]);
lcurveMapping.put(parseInt, ep[1]);
} catch (NumberFormatException e) {
logger.warn(format("Bad curve mapping. Integer needed for strength %s for %s in property %s",
ep[0], mape, SECURITY_CURVE_MAPPING));
}
}
}
return lcurveMapping;
}
/**
* Get the timeout for a single proposal request to endorser.
*
* @return the timeout in milliseconds.
*/
public long getProposalWaitTime() {
return Long.parseLong(getProperty(PROPOSAL_WAIT_TIME));
}
/**
* Get the configured time to wait for genesis block.
*
* @return time in milliseconds.
*/
public long getGenesisBlockWaitTime() {
return Long.parseLong(getProperty(GENESISBLOCK_WAIT_TIME));
}
/**
* Time to wait for channel to be configured.
*
* @return
*/
public long getChannelConfigWaitTime() {
return Long.parseLong(getProperty(CHANNEL_CONFIG_WAIT_TIME));
}
/**
* Time to wait before retrying an operation.
*
* @return
*/
public long getOrdererRetryWaitTime() {
return Long.parseLong(getProperty(ORDERER_RETRY_WAIT_TIME));
}
public long getOrdererWaitTime() {
return Long.parseLong(getProperty(ORDERER_WAIT_TIME));
}
/**
* getPeerEventRegistrationWaitTime
*
* @return time in milliseconds to wait for peer eventing service to wait for event registration
*/
public long getPeerEventRegistrationWaitTime() {
return Long.parseLong(getProperty(PEER_EVENT_REGISTRATION_WAIT_TIME));
}
/**
* getPeerEventRegistrationWaitTime
*
* @return time in milliseconds to wait for peer eventing service to wait for event registration
*/
public long getPeerRetryWaitTime() {
return Long.parseLong(getProperty(PEER_EVENT_RETRY_WAIT_TIME));
}
public long getPeerEventReconnectionWarningRate() {
return Long.parseLong(getProperty(PEER_EVENT_RECONNECTION_WARNING_RATE));
}
/**
* How often serviced discovery is preformed in seconds.
*
* @return
*/
public int getServiceDiscoveryFreqSeconds() {
return Integer.parseInt(getProperty(SERVICE_DISCOVER_FREQ_SECONDS));
}
/**
* Time to wait for service discovery to complete.
*
* @return
*/
public int getServiceDiscoveryWaitTime() {
return Integer.parseInt(getProperty(SERVICE_DISCOVER_WAIT_TIME));
}
public boolean discoverAsLocalhost() {
return Boolean.parseBoolean(getProperty(SERVICE_DISCOVER_AS_LOCALHOST));
}
public String getAsymmetricKeyType() {
return getProperty(ASYMMETRIC_KEY_TYPE);
}
public String getCertificateFormat() {
return getProperty(CERTIFICATE_FORMAT);
}
public String getSignatureAlgorithm() {
return getProperty(SIGNATURE_ALGORITHM);
}
public String getDefaultCryptoSuiteFactory() {
return getProperty(DEFAULT_CRYPTO_SUITE_FACTORY);
}
public int maxLogStringLength() {
return Integer.parseInt(getProperty(MAX_LOG_STRING_LENGTH));
}
/**
* getProposalConsistencyValidation determine if validation of the proposals should
* be done before sending to the orderer.
*
* @return if true proposals will be checked they are consistent with each other before sending to the Orderer
*/
public boolean getProposalConsistencyValidation() {
return Boolean.parseBoolean(getProperty(PROPOSAL_CONSISTENCY_VALIDATION));
}
private int extraLogLevel = -1;
public boolean extraLogLevel(int val) {
if (extraLogLevel == -1) {
extraLogLevel = Integer.parseInt(getProperty(EXTRALOGLEVEL));
}
return val <= extraLogLevel;
}
DiagnosticFileDumper diagnosticFileDumper = null;
/**
* The directory where diagnostic dumps are to be place, null if none should be done.
*
* @return The directory where diagnostic dumps are to be place, null if none should be done.
*/
public DiagnosticFileDumper getDiagnosticFileDumper() {
if (diagnosticFileDumper != null) {
return diagnosticFileDumper;
}
String dd = sdkProperties.getProperty(DIAGNOTISTIC_FILE_DIRECTORY);
if (dd != null) {
diagnosticFileDumper = DiagnosticFileDumper.configInstance(new File(dd));
}
return diagnosticFileDumper;
}
/**
* This does NOT trigger futures time out and must be kept WELL above any expected future timeout
* for transactions sent to the Orderer
*
* @return
*/
public long getTransactionListenerCleanUpTimeout() {
return Long.parseLong(getProperty(TRANSACTION_CLEANUP_UP_TIMEOUT_WAIT_TIME));
}
/**
* The number of threads to keep in the pool, even if they are idle, unless {@code allowCoreThreadTimeOut} is set
*
* @return The number of threads to keep in the pool, even if they are idle, unless {@code allowCoreThreadTimeOut} is set
*/
public int getClientThreadExecutorCorePoolSize() {
return Integer.parseInt(getProperty(CLIENT_THREAD_EXECUTOR_COREPOOLSIZE));
}
/**
* maximumPoolSize the maximum number of threads to allow in the pool
*
* @return maximumPoolSize the maximum number of threads to allow in the pool
*/
public int getClientThreadExecutorMaxiumPoolSize() {
return Integer.parseInt(getProperty(CLIENT_THREAD_EXECUTOR_MAXIMUMPOOLSIZE));
}
/**
* keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
*
* @return The keep alive time.
*/
public long getClientThreadExecutorKeepAliveTime() {
return Long.parseLong(getProperty(CLIENT_THREAD_EXECUTOR_KEEPALIVETIME));
}
/**
* the time unit for the argument
*
* @return
*/
public TimeUnit getClientThreadExecutorKeepAliveTimeUnit() {
return TimeUnit.valueOf(getProperty(CLIENT_THREAD_EXECUTOR_KEEPALIVETIMEUNIT));
}
/**
* The default chaincode Endorsement policy plugin
* <p>
* This should never need setting
*
* @return The default chaincode Endorsement policy plugin
*/
public String getDefaultChaincodeEndorsementPlugin() {
return getProperty(LIFECYCLE_CHAINCODE_ENDORSEMENT_PLUGIN);
}
/**
* The default chaincode validation plugin
* This should never need setting.
*
* @return The default chaincode validation plugin
*/
public String getDefaultChaincodeValidationPlugin() {
return getProperty(LIFECYCLE_CHAINCODE_VALIDATION_PLUGIN);
}
/**
* Whether require init method in chaincode to be run.
* The default will return null which will not set the Fabric protobuf value which then sets false. False is the Fabric
* default.
*
* @return The default setting for initRequired in chaincode approve for my org and commit chaincode definition.
*/
public Boolean getLifecycleInitRequiredDefault() {
String property = getProperty(LIFECYCLE_INITREQUIREDDEFAULT);
if (property != null) {
return Boolean.parseBoolean(property);
}
return null;
}
}

View File

@ -1,204 +0,0 @@
/*
*
* Copyright 2016,2017 DTCC, Fujitsu Australia Software Technology, IBM - All Rights Reserved.
*
* 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 com.chinaunicom.mall.ebtp.common.crypto.helper;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.TimeZone;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Dumps files for diagnostic purposes
*/
public class DiagnosticFileDumper implements Runnable {
private final File directory;
private final String dirAbsolutePath;
private final String pid;
// private static final Log logger = LogFactory.getLog(DiagnosticFileDumper.class);
private static Thread thread;
private final BlockingQueue<QueEntry> queEntries = new LinkedBlockingQueue<>();
private static DiagnosticFileDumper singleInstance = null;
private static final AtomicInteger counter = new AtomicInteger(0);
private DiagnosticFileDumper(File directory) {
this.directory = directory;
this.dirAbsolutePath = directory == null ? null : directory.getAbsolutePath();
this.pid = getPID() + "";
}
static DiagnosticFileDumper configInstance(File directory) {
if (singleInstance == null) {
singleInstance = new DiagnosticFileDumper(directory);
thread = new Thread(singleInstance);
thread.setName("DiagnosticFileDumper");
thread.setDaemon(true);
thread.start();
}
return singleInstance;
}
public String createDiagnosticProtobufFile(byte[] byteString) {
return createDiagnosticFile(byteString, "protobuf_", "proto");
}
private boolean cantWrite() {
return null == directory || !directory.exists() || !directory.isDirectory() || !directory.canWrite();
}
public String createDiagnosticFile(byte[] bytes) {
return createDiagnosticFile(bytes, null, null);
}
public String createDiagnosticTarFile(byte[] bytes) {
return createDiagnosticFile(bytes, null, "tgz");
}
public String createDiagnosticFile(String msg) {
return createDiagnosticFile(msg.getBytes(StandardCharsets.UTF_8), null, null);
}
public String createDiagnosticFile(byte[] bytes, String prefix, String ext) {
String fileName = "";
if (cantWrite()) {
return "Missing dump directory or can not write: " + (dirAbsolutePath);
}
if (null != bytes) {
if (null == prefix) {
prefix = "diagnostic_";
}
if (null == ext) {
ext = "bin";
}
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss_SSS");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("UTC"));
fileName = prefix + dateFormatGmt.format(new Date()) + "P" + pid + "_" + Thread.currentThread().getId()
+ "_" + counter.addAndGet(1) + "." + ext;
fileName = fileName.replaceAll("\\:", "-"); // colon is bad for windows.
new QueEntry(fileName, bytes); //Add to Que let process by async thread.
}
return fileName;
}
@Override
public void run() {
while (true) {
try {
final LinkedList<QueEntry> entries = new LinkedList<>();
entries.add(this.queEntries.take()); // wait on one.
this.queEntries.drainTo(entries); //got one, see if there are more.
if (cantWrite()) {
return; //IF the directory is missing just assume user does not want diagnostic files created anymore.
}
entries.forEach(queEntry -> {
try {
final AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get(dirAbsolutePath, queEntry.fileName),
StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
channel.write(ByteBuffer.wrap(queEntry.dataBytes), 0, null, new CompletionHandler<Integer, Object>() {
@Override
public void completed(Integer result, Object attachment) {
try {
channel.close();
} catch (IOException e) {
//best effort
}
}
@Override
public void failed(Throwable exc, Object attachment) {
try {
channel.close();
} catch (IOException e) {
//best effort.
}
}
});
} catch (IOException e) {
//best effort.
}
});
} catch (InterruptedException e) {
// best effort
}
}
}
class QueEntry {
final String fileName;
final byte[] dataBytes;
QueEntry(String fileName, byte[] dataBytes) {
this.fileName = fileName;
this.dataBytes = dataBytes;
queEntries.add(this);
}
}
private static long getPID() {
String processName =
java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
return Long.parseLong(processName.split("@")[0]);
}
}

View File

@ -1,409 +0,0 @@
/*
* Copyright 2017 DTCC, Fujitsu Australia Software Technology, IBM - All Rights Reserved.
*
* 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 com.chinaunicom.mall.ebtp.common.crypto.helper;
import com.google.protobuf.ByteString;
import com.google.protobuf.Timestamp;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA3Digest;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Hex;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.SecureRandom;
import java.time.Instant;
import java.util.Comparator;
import java.util.List;
import java.util.Properties;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.String.format;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.commons.codec.binary.Hex.encodeHexString;
public final class Utils {
private static final Log logger = LogFactory.getLog(Utils.class);
private static final boolean TRACE_ENABED = logger.isTraceEnabled();
private static final Config config = Config.getConfig();
private static final int MAX_LOG_STRING_LENGTH = config.maxLogStringLength();
/**
* Generate parameter hash for the given chaincode path,func and args
*
* @param path Chaincode path
* @param func Chaincode function name
* @param args List of arguments
* @return hash of path, func and args
*/
public static String generateParameterHash(String path, String func, List<String> args) {
logger.debug(format("GenerateParameterHash : path=%s, func=%s, args=%s", path, func, args));
// Append the arguments
StringBuilder param = new StringBuilder(path);
param.append(func);
args.forEach(param::append);
// Compute the hash
return Hex.toHexString(hash(param.toString().getBytes(UTF_8), new SHA3Digest()));
}
/**
* Generate hash of a chaincode directory
*
* @param rootDir Root directory
* @param chaincodeDir Channel code directory
* @param hash Previous hash (if any)
* @return hash of the directory
* @throws IOException
*/
public static String generateDirectoryHash(String rootDir, String chaincodeDir, String hash) throws IOException {
// Generate the project directory
Path projectPath;
if (rootDir == null) {
projectPath = Paths.get(chaincodeDir);
} else {
projectPath = Paths.get(rootDir, chaincodeDir);
}
File dir = projectPath.toFile();
if (!dir.exists() || !dir.isDirectory()) {
throw new IOException(format("The chaincode path \"%s\" is invalid", projectPath));
}
StringBuilder hashBuilder = new StringBuilder(hash);
Files.walk(projectPath)
.sorted(Comparator.naturalOrder())
.filter(Files::isRegularFile)
.map(Path::toFile)
.forEach(file -> {
try {
byte[] buf = readFile(file);
byte[] toHash = Arrays.concatenate(buf, hashBuilder.toString().getBytes(UTF_8));
hashBuilder.setLength(0);
hashBuilder.append(Hex.toHexString(hash(toHash, new SHA3Digest())));
} catch (IOException ex) {
throw new RuntimeException(format("Error while reading file %s", file.getAbsolutePath()), ex);
}
});
// If original hash and final hash are the same, it indicates that no new contents were found
if (hashBuilder.toString().equals(hash)) {
throw new IOException(format("The chaincode directory \"%s\" has no files", projectPath));
}
return hashBuilder.toString();
}
/**
* Compress the contents of given directory using Tar and Gzip to an in-memory byte array.
*
* @param sourceDirectory the source directory.
* @param pathPrefix a path to be prepended to every file name in the .tar.gz output, or {@code null} if no prefix is required.
* @param chaincodeMetaInf
* @return the compressed directory contents.
* @throws IOException
*/
public static byte[] generateTarGz(File sourceDirectory, String pathPrefix, File chaincodeMetaInf) throws IOException {
logger.trace(format("generateTarGz: sourceDirectory: %s, pathPrefix: %s, chaincodeMetaInf: %s",
sourceDirectory == null ? "null" : sourceDirectory.getAbsolutePath(), pathPrefix,
chaincodeMetaInf == null ? "null" : chaincodeMetaInf.getAbsolutePath()));
ByteArrayOutputStream bos = new ByteArrayOutputStream(500000);
String sourcePath = sourceDirectory.getAbsolutePath();
// try (TarArchiveOutputStream archiveOutputStream = new TarArchiveOutputStream(new GzipCompressorOutputStream(bos))) {
// archiveOutputStream.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
//
// Collection<File> childrenFiles = org.apache.commons.io.FileUtils.listFiles(sourceDirectory, null, true);
//
// ArchiveEntry archiveEntry;
// for (File childFile : childrenFiles) {
// String childPath = childFile.getAbsolutePath();
// String relativePath = childPath.substring((sourcePath.length() + 1));
//
// if (pathPrefix != null) {
// relativePath = Utils.combinePaths(pathPrefix, relativePath);
// }
//
// relativePath = FilenameUtils.separatorsToUnix(relativePath);
//
// if (TRACE_ENABED) {
// logger.trace(format("generateTarGz: Adding '%s' entry from source '%s' to archive.", relativePath, childFile.getAbsolutePath()));
// }
//
// archiveEntry = new TarArchiveEntry(childFile, relativePath);
// archiveOutputStream.putArchiveEntry(archiveEntry);
//
// try (FileInputStream fileInputStream = new FileInputStream(childFile)) {
// IOUtils.copy(fileInputStream, archiveOutputStream);
// } finally {
// archiveOutputStream.closeArchiveEntry();
// }
//
// }
//
// if (null != chaincodeMetaInf) {
// childrenFiles = org.apache.commons.io.FileUtils.listFiles(chaincodeMetaInf, null, true);
//
// final URI metabase = chaincodeMetaInf.toURI();
//
// for (File childFile : childrenFiles) {
//
// final String relativePath = Paths.get("META-INF", metabase.relativize(childFile.toURI()).getPath()).toString();
//
// if (TRACE_ENABED) {
// logger.trace(format("generateTarGz: Adding '%s' entry from source '%s' to archive.", relativePath, childFile.getAbsolutePath()));
// }
//
// archiveEntry = new TarArchiveEntry(childFile, relativePath);
// archiveOutputStream.putArchiveEntry(archiveEntry);
//
// try (FileInputStream fileInputStream = new FileInputStream(childFile)) {
// IOUtils.copy(fileInputStream, archiveOutputStream);
// } finally {
// archiveOutputStream.closeArchiveEntry();
// }
//
// }
//
// }
// }
return bos.toByteArray();
}
/**
* Read the contents a file.
*
* @param input source file to read.
* @return contents of the file.
* @throws IOException
*/
public static byte[] readFile(File input) throws IOException {
return Files.readAllBytes(Paths.get(input.getAbsolutePath()));
}
/**
* Generate a v4 UUID
*
* @return String representation of {@link UUID}
*/
public static String generateUUID() {
return UUID.randomUUID().toString();
}
/**
* Create a new {@link Timestamp} instance based on the current time
*
* @return timestamp
*/
public static Timestamp generateTimestamp() {
Instant time = Instant.now();
return Timestamp.newBuilder().setSeconds(time.getEpochSecond())
.setNanos(time.getNano()).build();
}
/**
* Delete a file or directory
*
* @param file {@link File} representing file or directory
* @throws IOException
*/
public static void deleteFileOrDirectory(File file) throws IOException {
if (file.exists()) {
if (file.isDirectory()) {
Path rootPath = Paths.get(file.getAbsolutePath());
Files.walk(rootPath, FileVisitOption.FOLLOW_LINKS)
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
} else {
file.delete();
}
} else {
throw new RuntimeException("File or directory does not exist");
}
}
/**
* Generate hash of the given input using the given Digest.
*
* @param input input data.
* @param digest the digest to use for hashing
* @return hashed data.
*/
public static byte[] hash(byte[] input, Digest digest) {
byte[] retValue = new byte[digest.getDigestSize()];
digest.update(input, 0, input.length);
digest.doFinal(retValue, 0);
return retValue;
}
/**
* Combine two or more paths
*
* @param first parent directory path
* @param other children
* @return combined path
*/
public static String combinePaths(String first, String... other) {
return Paths.get(first, other).toString();
}
/**
* Read a file from classpath
*
* @param fileName
* @return byte[] data
* @throws IOException
*/
public static byte[] readFileFromClasspath(String fileName) throws IOException {
try (InputStream is = Utils.class.getClassLoader().getResourceAsStream(fileName)) {
return IOUtils.toByteArray(is);
}
}
public static Properties parseGrpcUrl(String url) {
if (isNullOrEmpty(url)) {
throw new RuntimeException("URL cannot be null or empty");
}
Properties props = new Properties();
Pattern p = Pattern.compile("([^:]+)[:]//([^:]+)[:]([0-9]+)", Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(url);
if (m.matches()) {
props.setProperty("protocol", m.group(1));
props.setProperty("host", m.group(2));
props.setProperty("port", m.group(3));
String protocol = props.getProperty("protocol");
if (!"grpc".equals(protocol) && !"grpcs".equals(protocol)) {
throw new RuntimeException(format("Invalid protocol expected grpc or grpcs and found %s.", protocol));
}
} else {
throw new RuntimeException("URL must be of the format protocol://host:port. Found: '" + url + "'");
}
// TODO: allow all possible formats of the URL
return props;
}
/**
* Check if the strings Grpc url is valid
*
* @param url
* @return Return the io.seata.core.exception that indicates the error or null if ok.
*/
public static Exception checkGrpcUrl(String url) {
try {
parseGrpcUrl(url);
return null;
} catch (Exception e) {
return e;
}
}
/**
* Check if a string is null or empty.
*
* @param url the string to test.
* @return {@code true} if the string is null or empty; otherwise {@code false}.
*/
public static boolean isNullOrEmpty(String url) {
return url == null || url.isEmpty();
}
/**
* Makes logging strings which can be long or with unprintable characters be logged and trimmed.
*
* @param string Unsafe string too long
* @return returns a string which does not have unprintable characters and trimmed in length.
*/
public static String logString(final String string) {
if (string == null || string.length() == 0) {
return string;
}
String ret = string.replaceAll("[^\\p{Print}]", "?");
ret = ret.substring(0, Math.min(ret.length(), MAX_LOG_STRING_LENGTH)) + (ret.length() > MAX_LOG_STRING_LENGTH ? "..." : "");
return ret;
}
private static final int NONONCE_LENGTH = 24;
private static final SecureRandom RANDOM = new SecureRandom();
public static byte[] generateNonce() {
byte[] values = new byte[NONONCE_LENGTH];
RANDOM.nextBytes(values);
return values;
}
public static String toHexString(ByteString byteString) {
if (byteString == null) {
return null;
}
return encodeHexString(byteString.toByteArray());
}
public static String toHexString(byte[] bytes) {
if (bytes == null) {
return null;
}
return encodeHexString(bytes);
}
public static String toHexString(String bytes) {
if (bytes == null) {
return null;
}
return encodeHexString(bytes.getBytes(UTF_8));
}
/**
* Private constructor to prevent instantiation.
*/
private Utils() {
}
}

View File

@ -1,976 +0,0 @@
/*
* Copyright 2016, 2017 DTCC, Fujitsu Australia Software Technology, IBM - All Rights Reserved.
*
* 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 com.chinaunicom.mall.ebtp.common.crypto.security;
import com.chinaunicom.mall.ebtp.common.crypto.exception.CryptoException;
import com.chinaunicom.mall.ebtp.common.crypto.exception.InvalidArgumentException;
import com.chinaunicom.mall.ebtp.common.crypto.helper.Config;
import com.chinaunicom.mall.ebtp.common.crypto.helper.DiagnosticFileDumper;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.digests.SHA3Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import javax.security.auth.x500.X500Principal;
import javax.xml.bind.DatatypeConverter;
import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.*;
import java.security.interfaces.ECPrivateKey;
import java.security.spec.ECGenParameterSpec;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.chinaunicom.mall.ebtp.common.crypto.helper.Utils.isNullOrEmpty;
import static java.lang.String.format;
public class CryptoPrimitives implements CryptoSuite {
private static final Log logger = LogFactory.getLog(CryptoPrimitives.class);
private static final Config config = Config.getConfig();
private static final boolean IS_TRACE_LEVEL = logger.isTraceEnabled();
private static final DiagnosticFileDumper diagnosticFileDumper = IS_TRACE_LEVEL
? config.getDiagnosticFileDumper() : null;
private String curveName;
private CertificateFactory cf;
private Provider SECURITY_PROVIDER;
private String hashAlgorithm = config.getHashAlgorithm();
private int securityLevel = config.getSecurityLevel();
private String CERTIFICATE_FORMAT = config.getCertificateFormat();
private String DEFAULT_SIGNATURE_ALGORITHM = config.getSignatureAlgorithm();
private Map<Integer, String> securityCurveMapping = config.getSecurityCurveMapping();
// Following configuration settings are hardcoded as they don't deal with any interactions with Fabric MSP and BCCSP components
// If you wish to make these customizable, follow the logic from setProperties();
//TODO May need this for TCERTS ?
// private String ASYMMETRIC_KEY_TYPE = "EC";
// private String KEY_AGREEMENT_ALGORITHM = "ECDH";
// private String SYMMETRIC_KEY_TYPE = "AES";
// private int SYMMETRIC_KEY_BYTE_COUNT = 32;
// private String SYMMETRIC_ALGORITHM = "AES/CFB/NoPadding";
// private int MAC_KEY_BYTE_COUNT = 32;
public CryptoPrimitives() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
String securityProviderClassName = config.getSecurityProviderClassName();
SECURITY_PROVIDER = setUpExplicitProvider(securityProviderClassName);
//Decided TO NOT do this as it can have affects over the whole JVM and could have
// unexpected results. The embedding application can easily do this!
// Leaving this here as a warning.
// Security.insertProviderAt(SECURITY_PROVIDER, 1); // 1 is top not 0 :)
}
Provider setUpExplicitProvider(String securityProviderClassName) throws InstantiationException, ClassNotFoundException, IllegalAccessException {
if (null == securityProviderClassName) {
throw new InstantiationException(format("Security provider class name property (%s) set to null ", Config.SECURITY_PROVIDER_CLASS_NAME));
}
if (CryptoSuiteFactory.DEFAULT_JDK_PROVIDER.equals(securityProviderClassName)) {
return null;
}
Class<?> aClass = Class.forName(securityProviderClassName);
if (null == aClass) {
throw new InstantiationException(format("Getting class for security provider %s returned null ", securityProviderClassName));
}
if (!Provider.class.isAssignableFrom(aClass)) {
throw new InstantiationException(format("Class for security provider %s is not a Java security provider", aClass.getName()));
}
Provider securityProvider = (Provider) aClass.newInstance();
if (securityProvider == null) {
throw new InstantiationException(format("Creating instance of security %s returned null ", aClass.getName()));
}
return securityProvider;
}
// /**
// * sets the signature algorithm used for signing/verifying.
// *
// * @param sigAlg the name of the signature algorithm. See the list of valid names in the JCA Standard Algorithm Name documentation
// */
// public void setSignatureAlgorithm(String sigAlg) {
// this.DEFAULT_SIGNATURE_ALGORITHM = sigAlg;
// }
// /**
// * returns the signature algorithm used by this instance of CryptoPrimitives.
// * Note that fabric and fabric-ca have not yet standardized on which algorithms are supported.
// * While that plays out, CryptoPrimitives will try the algorithm specified in the certificate and
// * the default SHA256withECDSA that's currently hardcoded for fabric and fabric-ca
// *
// * @return the name of the signature algorithm
// */
// public String getSignatureAlgorithm() {
// return this.DEFAULT_SIGNATURE_ALGORITHM;
// }
@Override
public Certificate bytesToCertificate(byte[] certBytes) throws CryptoException {
if (certBytes == null || certBytes.length == 0) {
throw new CryptoException("bytesToCertificate: input null or zero length");
}
return getX509Certificate(certBytes);
// X509Certificate certificate;
// try {
// BufferedInputStream pem = new BufferedInputStream(new ByteArrayInputStream(certBytes));
// CertificateFactory certFactory = CertificateFactory.getInstance(CERTIFICATE_FORMAT);
// certificate = (X509Certificate) certFactory.generateCertificate(pem);
// } catch (CertificateException e) {
// String emsg = "Unable to converts byte array to certificate. error : " + e.getMessage();
// logger.error(emsg);
// logger.debug("input bytes array :" + new String(certBytes));
// throw new CryptoException(emsg, e);
// }
//
// return certificate;
}
/**
* Return X509Certificate from pem bytes.
* So you may ask why this ? Well some providers (BC) seems to have problems with creating the
* X509 cert from bytes so here we go through all available providers till one can convert. :)
*
* @param pemCertificate
* @return
*/
private X509Certificate getX509Certificate(byte[] pemCertificate) throws CryptoException {
X509Certificate ret = null;
CryptoException rete = null;
List<Provider> providerList = new LinkedList<>(Arrays.asList(Security.getProviders()));
if (SECURITY_PROVIDER != null) { //Add if overridden
providerList.add(SECURITY_PROVIDER);
}
try {
providerList.add(BouncyCastleProvider.class.newInstance()); // bouncy castle is there always.
} catch (Exception e) {
logger.warn(e);
}
for (Provider provider : providerList) {
try {
if (null == provider) {
continue;
}
CertificateFactory certFactory = CertificateFactory.getInstance(CERTIFICATE_FORMAT, provider);
if (null != certFactory) {
try (ByteArrayInputStream bis = new ByteArrayInputStream(pemCertificate)) {
Certificate certificate = certFactory.generateCertificate(bis);
if (certificate instanceof X509Certificate) {
ret = (X509Certificate) certificate;
rete = null;
break;
}
}
}
} catch (Exception e) {
rete = new CryptoException(e.getMessage(), e);
}
}
if (null != rete) {
throw rete;
}
if (ret == null) {
logger.error("Could not convert pem bytes");
}
return ret;
}
/**
* Return PrivateKey from pem bytes.
*
* @param pemKey pem-encoded private key
* @return
*/
public PrivateKey bytesToPrivateKey(byte[] pemKey) throws CryptoException {
PrivateKey pk;
try {
PemReader pr = new PemReader(new StringReader(new String(pemKey)));
PemObject po = pr.readPemObject();
PEMParser pem = new PEMParser(new StringReader(new String(pemKey)));
if (po.getType().equals("PRIVATE KEY")) {
pk = new JcaPEMKeyConverter().getPrivateKey((PrivateKeyInfo) pem.readObject());
} else {
logger.trace("Found private key with type " + po.getType());
PEMKeyPair kp = (PEMKeyPair) pem.readObject();
pk = new JcaPEMKeyConverter().getPrivateKey(kp.getPrivateKeyInfo());
}
} catch (Exception e) {
throw new CryptoException("Failed to convert private key bytes", e);
}
return pk;
}
@Override
public boolean verify(byte[] pemCertificate, String signatureAlgorithm, byte[] signature, byte[] plainText) throws CryptoException {
boolean isVerified = false;
if (plainText == null || signature == null || pemCertificate == null) {
return false;
}
if (config.extraLogLevel(10)) {
if (null != diagnosticFileDumper) {
String message = "plaintext in hex: " + DatatypeConverter.printHexBinary(plainText) + '\n' +
"signature in hex: " + DatatypeConverter.printHexBinary(signature) + '\n' +
"PEM cert in hex: " + DatatypeConverter.printHexBinary(pemCertificate);
logger.trace("verify : " +
diagnosticFileDumper.createDiagnosticFile(message));
}
}
try {
X509Certificate certificate = getX509Certificate(pemCertificate);
if (certificate != null) {
//isVerified = validateCertificate(certificate);
isVerified = true;
if (isVerified) { // only proceed if cert is trusted
Signature sig = Signature.getInstance(signatureAlgorithm);
sig.initVerify(certificate);
sig.update(plainText);
isVerified = sig.verify(signature);
}
}
} catch (InvalidKeyException e) {
CryptoException ex = new CryptoException("Cannot verify signature. Error is: "
+ e.getMessage() + "\r\nCertificate: "
+ DatatypeConverter.printHexBinary(pemCertificate), e);
logger.error(ex.getMessage(), ex);
throw ex;
} catch (NoSuchAlgorithmException | SignatureException e) {
CryptoException ex = new CryptoException("Cannot verify. Signature algorithm is invalid. Error is: " + e.getMessage(), e);
logger.error(ex.getMessage(), ex);
throw ex;
}
return isVerified;
} // verify
private KeyStore trustStore = null;
private void createTrustStore() throws CryptoException {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
setTrustStore(keyStore);
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException | InvalidArgumentException e) {
throw new CryptoException("Cannot create trust store. Error: " + e.getMessage(), e);
}
}
/**
* setTrustStore uses the given KeyStore object as the container for trusted
* certificates
*
* @param keyStore the KeyStore which will be used to hold trusted certificates
* @throws InvalidArgumentException
*/
private void setTrustStore(KeyStore keyStore) throws InvalidArgumentException {
if (keyStore == null) {
throw new InvalidArgumentException("Need to specify a java.security.KeyStore input parameter");
}
trustStore = keyStore;
}
/**
* getTrustStore returns the KeyStore object where we keep trusted certificates.
* If no trust store has been set, this method will create one.
*
* @return the trust store as a java.security.KeyStore object
* @throws CryptoException
* @see KeyStore
*/
public KeyStore getTrustStore() throws CryptoException {
if (trustStore == null) {
createTrustStore();
}
return trustStore;
}
/**
* addCACertificateToTrustStore adds a CA cert to the set of certificates used for signature validation
*
* @param caCertPem an X.509 certificate in PEM format
* @param alias an alias associated with the certificate. Used as shorthand for the certificate during crypto operations
* @throws CryptoException
* @throws InvalidArgumentException
*/
public void addCACertificateToTrustStore(File caCertPem, String alias) throws CryptoException, InvalidArgumentException {
if (caCertPem == null) {
throw new InvalidArgumentException("The certificate cannot be null");
}
if (alias == null || alias.isEmpty()) {
throw new InvalidArgumentException("You must assign an alias to a certificate when adding to the trust store");
}
try {
try (BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(FileUtils.readFileToByteArray(caCertPem)))) {
Certificate caCert = cf.generateCertificate(bis);
addCACertificateToTrustStore(caCert, alias);
}
} catch (CertificateException | IOException e) {
throw new CryptoException("Unable to add CA certificate to trust store. Error: " + e.getMessage(), e);
}
}
/**
* addCACertificatesToTrustStore adds a CA certs in a stream to the trust store used for signature validation
*
* @param bis an X.509 certificate stream in PEM format in bytes
* @throws CryptoException
* @throws InvalidArgumentException
*/
public void addCACertificatesToTrustStore(BufferedInputStream bis) throws CryptoException, InvalidArgumentException {
if (bis == null) {
throw new InvalidArgumentException("The certificate stream bis cannot be null");
}
try {
final Collection<? extends Certificate> certificates = cf.generateCertificates(bis);
for (Certificate certificate : certificates) {
addCACertificateToTrustStore(certificate);
}
} catch (CertificateException e) {
throw new CryptoException("Unable to add CA certificate to trust store. Error: " + e.getMessage(), e);
}
}
final Set<String> certificateSet = ConcurrentHashMap.newKeySet();
private void addCACertificateToTrustStore(Certificate certificate) throws InvalidArgumentException, CryptoException {
String alias;
if (certificate instanceof X509Certificate) {
alias = ((X509Certificate) certificate).getSerialNumber().toString();
} else { // not likely ...
alias = Integer.toString(certificate.hashCode());
}
addCACertificateToTrustStore(certificate, alias);
}
/**
* addCACertificateToTrustStore adds a CA cert to the set of certificates used for signature validation
*
* @param caCert an X.509 certificate
* @param alias an alias associated with the certificate. Used as shorthand for the certificate during crypto operations
* @throws CryptoException
* @throws InvalidArgumentException
*/
void addCACertificateToTrustStore(Certificate caCert, String alias) throws InvalidArgumentException, CryptoException {
if (alias == null || alias.isEmpty()) {
throw new InvalidArgumentException("You must assign an alias to a certificate when adding to the trust store.");
}
if (caCert == null) {
throw new InvalidArgumentException("Certificate cannot be null.");
}
try {
if (config.extraLogLevel(10)) {
if (null != diagnosticFileDumper) {
logger.trace(format("Adding cert to trust store. alias: %s. certificate:", alias) + diagnosticFileDumper.createDiagnosticFile(alias + "cert: " + caCert.toString()));
}
}
synchronized (certificateSet) {
if (certificateSet.contains(alias)) {
return;
}
getTrustStore().setCertificateEntry(alias, caCert);
certificateSet.add(alias);
}
} catch (KeyStoreException e) {
String emsg = "Unable to add CA certificate to trust store. Error: " + e.getMessage();
logger.error(emsg, e);
throw new CryptoException(emsg, e);
}
}
@Override
public void loadCACertificates(Collection<Certificate> certificates) throws CryptoException {
if (certificates == null || certificates.size() == 0) {
throw new CryptoException("Unable to load CA certificates. List is empty");
}
try {
for (Certificate cert : certificates) {
addCACertificateToTrustStore(cert);
}
} catch (InvalidArgumentException e) {
// Note: This can currently never happen (as cert<>null and alias<>null)
throw new CryptoException("Unable to add certificate to trust store. Error: " + e.getMessage(), e);
}
}
/* (non-Javadoc)
* @see org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.security.CryptoSuite#loadCACertificatesAsBytes(java.util.Collection)
*/
@Override
public void loadCACertificatesAsBytes(Collection<byte[]> certificatesBytes) throws CryptoException {
if (certificatesBytes == null || certificatesBytes.size() == 0) {
throw new CryptoException("List of CA certificates is empty. Nothing to load.");
}
ArrayList<Certificate> certList = new ArrayList<>();
for (byte[] certBytes : certificatesBytes) {
certList.add(bytesToCertificate(certBytes));
}
loadCACertificates(certList);
}
/**
* Adds a CA certificate with a private key and password.
*
* @param clientKey the private key bytes input stream. Cannot be null.
* @param clientCert the client certificate bytes input stream. Cannot be null.
* @param clientKeyPassword the password as a String. Can be null.
*/
public void addClientCACertificateToTrustStore(byte[] clientKey, byte[] clientCert, String clientKeyPassword) throws CryptoException, IllegalArgumentException {
if (clientKey == null) {
throw new IllegalArgumentException("Client key byte input stream is required.");
}
if (clientCert == null) {
throw new IllegalArgumentException("Client certificate byte input stream is required.");
}
try {
Certificate tlsClientCertificate = bytesToCertificate(clientCert);
String alias;
if (tlsClientCertificate instanceof X509Certificate) {
alias = ((X509Certificate) tlsClientCertificate).getSerialNumber().toString();
} else { // not likely ...
alias = Integer.toString(tlsClientCertificate.hashCode());
}
char[] password = clientKeyPassword == null ? new char[0] : clientKeyPassword.toCharArray();
getTrustStore().setKeyEntry(alias, bytesToPrivateKey(clientKey), password, new Certificate[]{tlsClientCertificate});
} catch (KeyStoreException e) {
throw new CryptoException("Unable to add client CA certificate to trust store.", e);
}
}
/**
* validateCertificate checks whether the given certificate is trusted. It
* checks if the certificate is signed by one of the trusted certs in the
* trust store.
*
* @param certPEM the certificate in PEM format
* @return true if the certificate is trusted
*/
boolean validateCertificate(byte[] certPEM) {
if (certPEM == null) {
return false;
}
try {
X509Certificate certificate = getX509Certificate(certPEM);
if (null == certificate) {
throw new Exception("Certificate transformation returned null");
}
return validateCertificate(certificate);
} catch (Exception e) {
logger.error("Cannot validate certificate. Error is: " + e.getMessage() + "\r\nCertificate (PEM, hex): "
+ DatatypeConverter.printHexBinary(certPEM));
return false;
}
}
boolean validateCertificate(Certificate cert) {
boolean isValidated;
if (cert == null) {
return false;
}
try {
KeyStore keyStore = getTrustStore();
PKIXParameters parms = new PKIXParameters(keyStore);
parms.setRevocationEnabled(false);
CertPathValidator certValidator = CertPathValidator.getInstance(CertPathValidator.getDefaultType()); // PKIX
ArrayList<Certificate> start = new ArrayList<>();
start.add(cert);
CertificateFactory certFactory = CertificateFactory.getInstance(CERTIFICATE_FORMAT);
CertPath certPath = certFactory.generateCertPath(start);
certValidator.validate(certPath, parms);
isValidated = true;
} catch (KeyStoreException | InvalidAlgorithmParameterException | NoSuchAlgorithmException
| CertificateException | CertPathValidatorException | CryptoException e) {
logger.error("Cannot validate certificate. Error is: " + e.getMessage() + "\r\nCertificate"
+ cert.toString());
isValidated = false;
}
return isValidated;
} // validateCertificate
/**
* Security Level determines the elliptic curve used in key generation
*
* @param securityLevel currently 256 or 384
* @throws InvalidArgumentException
*/
void setSecurityLevel(final int securityLevel) throws InvalidArgumentException {
logger.trace(format("setSecurityLevel to %d", securityLevel));
if (securityCurveMapping.isEmpty()) {
throw new InvalidArgumentException("Security curve mapping has no entries.");
}
if (!securityCurveMapping.containsKey(securityLevel)) {
StringBuilder sb = new StringBuilder();
String sp = "";
for (int x : securityCurveMapping.keySet()) {
sb.append(sp).append(x);
sp = ", ";
}
throw new InvalidArgumentException(format("Illegal security level: %d. Valid values are: %s", securityLevel, sb.toString()));
}
String lcurveName = securityCurveMapping.get(securityLevel);
logger.debug(format("Mapped curve strength %d to %s", securityLevel, lcurveName));
X9ECParameters params = ECNamedCurveTable.getByName(lcurveName);
//Check if can match curve name to requested strength.
if (params == null) {
InvalidArgumentException invalidArgumentException = new InvalidArgumentException(
format("Curve %s defined for security strength %d was not found.", curveName, securityLevel));
logger.error(invalidArgumentException);
throw invalidArgumentException;
}
curveName = lcurveName;
this.securityLevel = securityLevel;
}
void setHashAlgorithm(String algorithm) throws InvalidArgumentException {
if (isNullOrEmpty(algorithm)
|| !("SHA2".equals(algorithm) || "SHA3".equals(algorithm))) {
throw new InvalidArgumentException("Illegal Hash function family: "
+ algorithm + " - must be either SHA2 or SHA3");
}
hashAlgorithm = algorithm;
}
@Override
public KeyPair keyGen() throws CryptoException {
return ecdsaKeyGen();
}
private KeyPair ecdsaKeyGen() throws CryptoException {
return generateKey("EC", curveName);
}
private KeyPair generateKey(String encryptionName, String curveName) throws CryptoException {
try {
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec(curveName);
KeyPairGenerator g = SECURITY_PROVIDER == null ? KeyPairGenerator.getInstance(encryptionName) :
KeyPairGenerator.getInstance(encryptionName, SECURITY_PROVIDER);
g.initialize(ecGenSpec, new SecureRandom());
return g.generateKeyPair();
} catch (Exception exp) {
throw new CryptoException("Unable to generate key pair", exp);
}
}
/**
* Decodes an ECDSA signature and returns a two element BigInteger array.
*
* @param signature ECDSA signature bytes.
* @return BigInteger array for the signature's r and s values
* @throws Exception
*/
private static BigInteger[] decodeECDSASignature(byte[] signature) throws Exception {
try (ByteArrayInputStream inStream = new ByteArrayInputStream(signature)) {
ASN1InputStream asnInputStream = new ASN1InputStream(inStream);
ASN1Primitive asn1 = asnInputStream.readObject();
BigInteger[] sigs = new BigInteger[2];
int count = 0;
if (asn1 instanceof ASN1Sequence) {
ASN1Sequence asn1Sequence = (ASN1Sequence) asn1;
ASN1Encodable[] asn1Encodables = asn1Sequence.toArray();
for (ASN1Encodable asn1Encodable : asn1Encodables) {
ASN1Primitive asn1Primitive = asn1Encodable.toASN1Primitive();
if (asn1Primitive instanceof ASN1Integer) {
ASN1Integer asn1Integer = (ASN1Integer) asn1Primitive;
BigInteger integer = asn1Integer.getValue();
if (count < 2) {
sigs[count] = integer;
}
count++;
}
}
}
if (count != 2) {
throw new CryptoException(format("Invalid ECDSA signature. Expected count of 2 but got: %d. Signature is: %s", count,
DatatypeConverter.printHexBinary(signature)));
}
return sigs;
}
}
/**
* Sign data with the specified elliptic curve private key.
*
* @param privateKey elliptic curve private key.
* @param data data to sign
* @return the signed data.
* @throws CryptoException
*/
private byte[] ecdsaSignToBytes(ECPrivateKey privateKey, byte[] data) throws CryptoException {
if (data == null) {
throw new CryptoException("Data that to be signed is null.");
}
if (data.length == 0) {
throw new CryptoException("Data to be signed was empty.");
}
try {
X9ECParameters params = ECNamedCurveTable.getByName(curveName);
BigInteger curveN = params.getN();
Signature sig = SECURITY_PROVIDER == null ? Signature.getInstance(DEFAULT_SIGNATURE_ALGORITHM) :
Signature.getInstance(DEFAULT_SIGNATURE_ALGORITHM, SECURITY_PROVIDER);
sig.initSign(privateKey);
sig.update(data);
byte[] signature = sig.sign();
BigInteger[] sigs = preventMalleability(decodeECDSASignature(signature), curveN);
try (ByteArrayOutputStream s = new ByteArrayOutputStream()) {
DERSequenceGenerator seq = new DERSequenceGenerator(s);
seq.addObject(new ASN1Integer(sigs[0]));
seq.addObject(new ASN1Integer(sigs[1]));
seq.close();
return s.toByteArray();
}
} catch (Exception e) {
throw new CryptoException("Could not sign the message using private key", e);
}
}
/**
* @throws ClassCastException if the supplied private key is not of type {@link ECPrivateKey}.
*/
@Override
public byte[] sign(PrivateKey key, byte[] data) throws CryptoException {
return ecdsaSignToBytes((ECPrivateKey) key, data);
}
private BigInteger[] preventMalleability(BigInteger[] sigs, BigInteger curveN) {
BigInteger cmpVal = curveN.divide(BigInteger.valueOf(2L));
BigInteger sval = sigs[1];
if (sval.compareTo(cmpVal) > 0) {
sigs[1] = curveN.subtract(sval);
}
return sigs;
}
/**
* generateCertificationRequest
*
* @param subject The subject to be added to the certificate
* @param pair Public private key pair
* @return PKCS10CertificationRequest Certificate Signing Request.
* @throws OperatorCreationException
*/
@Override
public String generateCertificationRequest(String subject, KeyPair pair)
throws InvalidArgumentException {
try {
PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(
new X500Principal("CN=" + subject), pair.getPublic());
JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder("SHA256withECDSA");
if (null != SECURITY_PROVIDER) {
csBuilder.setProvider(SECURITY_PROVIDER);
}
ContentSigner signer = csBuilder.build(pair.getPrivate());
return certificationRequestToPEM(p10Builder.build(signer));
} catch (Exception e) {
logger.error(e);
throw new InvalidArgumentException(e);
}
}
/**
* certificationRequestToPEM - Convert a PKCS10CertificationRequest to PEM
* format.
*
* @param csr The Certificate to convert
* @return An equivalent PEM format certificate.
* @throws IOException
*/
private String certificationRequestToPEM(PKCS10CertificationRequest csr) throws IOException {
PemObject pemCSR = new PemObject("CERTIFICATE REQUEST", csr.getEncoded());
StringWriter str = new StringWriter();
JcaPEMWriter pemWriter = new JcaPEMWriter(str);
pemWriter.writeObject(pemCSR);
pemWriter.close();
str.close();
return str.toString();
}
// public PrivateKey ecdsaKeyFromPrivate(byte[] key) throws CryptoException {
// try {
// EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(key);
// KeyFactory generator = KeyFactory.getInstance("ECDSA", SECURITY_PROVIDER_NAME);
// PrivateKey privateKey = generator.generatePrivate(privateKeySpec);
//
// return privateKey;
// } catch (Exception exp) {
// throw new CryptoException("Unable to convert byte[] into PrivateKey", exp);
// }
// }
@Override
public byte[] hash(byte[] input) {
Digest digest = getHashDigest();
byte[] retValue = new byte[digest.getDigestSize()];
digest.update(input, 0, input.length);
digest.doFinal(retValue, 0);
return retValue;
}
@Override
public CryptoSuiteFactory getCryptoSuiteFactory() {
return HLSDKJCryptoSuiteFactory.instance(); //Factory for this crypto suite.
}
private final AtomicBoolean inited = new AtomicBoolean(false);
// @Override
public void init() throws CryptoException, InvalidArgumentException {
if (inited.getAndSet(true)) {
throw new InvalidArgumentException("Crypto suite already initialized");
} else {
resetConfiguration();
}
}
private Digest getHashDigest() {
if ("SHA3".equals(hashAlgorithm)) {
return new SHA3Digest();
} else {
// Default to SHA2
return new SHA256Digest();
}
}
// /**
// * Shake256 hash the supplied byte data.
// *
// * @param in byte array to be hashed.
// * @param bitLength of the result.
// * @return the hashed byte data.
// */
// public byte[] shake256(byte[] in, int bitLength) {
//
// if (bitLength % 8 != 0) {
// throw new IllegalArgumentException("bit length not modulo 8");
//
// }
//
// final int byteLen = bitLength / 8;
//
// SHAKEDigest sd = new SHAKEDigest(256);
//
// sd.update(in, 0, in.length);
//
// byte[] out = new byte[byteLen];
//
// sd.doFinal(out, 0, byteLen);
//
// return out;
//
// }
/**
* Resets curve name, hash algorithm and cert factory. Call this method when a config value changes
*
* @throws CryptoException
* @throws InvalidArgumentException
*/
private void resetConfiguration() throws CryptoException, InvalidArgumentException {
setSecurityLevel(securityLevel);
setHashAlgorithm(hashAlgorithm);
try {
cf = CertificateFactory.getInstance(CERTIFICATE_FORMAT);
} catch (CertificateException e) {
CryptoException ex = new CryptoException("Cannot initialize " + CERTIFICATE_FORMAT + " certificate factory. Error = " + e.getMessage(), e);
logger.error(ex.getMessage(), ex);
throw ex;
}
}
// /* (non-Javadoc)
// * @see org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.security.CryptoSuite#setProperties(java.util.Properties)
// */
// @Override
void setProperties(Properties properties) throws CryptoException, InvalidArgumentException {
if (properties == null) {
throw new InvalidArgumentException("properties must not be null");
}
// if (properties != null) {
hashAlgorithm = Optional.ofNullable(properties.getProperty(Config.HASH_ALGORITHM)).orElse(hashAlgorithm);
String secLevel = Optional.ofNullable(properties.getProperty(Config.SECURITY_LEVEL)).orElse(Integer.toString(securityLevel));
securityLevel = Integer.parseInt(secLevel);
if (properties.containsKey(Config.SECURITY_CURVE_MAPPING)) {
securityCurveMapping = Config.parseSecurityCurveMappings(properties.getProperty(Config.SECURITY_CURVE_MAPPING));
} else {
securityCurveMapping = config.getSecurityCurveMapping();
}
final String providerName = properties.containsKey(Config.SECURITY_PROVIDER_CLASS_NAME) ?
properties.getProperty(Config.SECURITY_PROVIDER_CLASS_NAME) :
config.getSecurityProviderClassName();
try {
SECURITY_PROVIDER = setUpExplicitProvider(providerName);
} catch (Exception e) {
throw new InvalidArgumentException(format("Getting provider for class name: %s", providerName), e);
}
CERTIFICATE_FORMAT = Optional.ofNullable(properties.getProperty(Config.CERTIFICATE_FORMAT)).orElse(CERTIFICATE_FORMAT);
DEFAULT_SIGNATURE_ALGORITHM = Optional.ofNullable(properties.getProperty(Config.SIGNATURE_ALGORITHM)).orElse(DEFAULT_SIGNATURE_ALGORITHM);
resetConfiguration();
}
/* (non-Javadoc)
* @see org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.security.CryptoSuite#getProperties()
*/
@Override
public Properties getProperties() {
Properties properties = new Properties();
properties.setProperty(Config.HASH_ALGORITHM, hashAlgorithm);
properties.setProperty(Config.SECURITY_LEVEL, Integer.toString(securityLevel));
properties.setProperty(Config.CERTIFICATE_FORMAT, CERTIFICATE_FORMAT);
properties.setProperty(Config.SIGNATURE_ALGORITHM, DEFAULT_SIGNATURE_ALGORITHM);
return properties;
}
public byte[] certificateToDER(String certificatePEM) {
byte[] content = null;
try (PemReader pemReader = new PemReader(new StringReader(certificatePEM))) {
final PemObject pemObject = pemReader.readPemObject();
content = pemObject.getContent();
} catch (IOException e) {
// best attempt
}
return content;
}
}

View File

@ -1,169 +0,0 @@
/*
* Copyright 2016,2017 DTCC, Fujitsu Australia Software Technology, IBM - All Rights Reserved.
*
* 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 com.chinaunicom.mall.ebtp.common.crypto.security;
import com.chinaunicom.mall.ebtp.common.crypto.exception.CryptoException;
import com.chinaunicom.mall.ebtp.common.crypto.exception.InvalidArgumentException;
import java.lang.reflect.InvocationTargetException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.util.Collection;
import java.util.Properties;
/**
* All packages for PKI key creation/signing/verification implement this interface
*/
public interface CryptoSuite {
/**
* Get Crypto Suite Factory for this implementation.
*
* @return MUST return the one and only one instance of a factory that produced this crypto suite.
*/
CryptoSuiteFactory getCryptoSuiteFactory();
/**
* @return the {@link Properties} object containing implementation specific key generation properties
*/
Properties getProperties();
/**
* Set the Certificate Authority certificates to be used when validating a certificate chain of trust
*
* @param certificates A collection of {@link Certificate}s
* @throws CryptoException
*/
void loadCACertificates(Collection<Certificate> certificates) throws CryptoException;
/**
* Set the Certificate Authority certificates to be used when validating a certificate chain of trust.
*
* @param certificates a collection of certificates in PEM format
* @throws CryptoException
*/
void loadCACertificatesAsBytes(Collection<byte[]> certificates) throws CryptoException;
/**
* Generate a key.
*
* @return the generated key.
* @throws CryptoException
*/
KeyPair keyGen() throws CryptoException;
/**
* Sign the specified byte string.
*
* @param key the {@link PrivateKey} to be used for signing
* @param plainText the byte string to sign
* @return the signed data.
* @throws CryptoException
*/
byte[] sign(PrivateKey key, byte[] plainText) throws CryptoException;
/**
* Verify the specified signature
*
* @param certificate the certificate of the signer as the contents of the PEM file
* @param signatureAlgorithm the algorithm used to create the signature.
* @param signature the signature to verify
* @param plainText the original text that is to be verified
* @return {@code true} if the signature is successfully verified; otherwise {@code false}.
* @throws CryptoException
*/
boolean verify(byte[] certificate, String signatureAlgorithm, byte[] signature, byte[] plainText) throws CryptoException;
/**
* Hash the specified text byte data.
*
* @param plainText the text to hash
* @return the hashed data.
*/
byte[] hash(byte[] plainText);
/**
* Generates a CertificationRequest
*
* @param user
* @param keypair
* @return String in PEM format for certificate request.
* @throws InvalidArgumentException
*/
String generateCertificationRequest(String user, KeyPair keypair) throws InvalidArgumentException;
/**
* Convert bytes in PEM format to Certificate.
*
* @param certBytes
* @return Certificate
* @throws CryptoException
*/
Certificate bytesToCertificate(byte[] certBytes) throws CryptoException, CryptoException;
/**
* The CryptoSuite factory. Currently {@link #getCryptoSuite} will always
* give you a {@link CryptoPrimitives} object
*/
class Factory {
private Factory() {
}
/**
* Get a crypto suite with the default factory with default settings.
* Settings which can define such parameters such as curve strength, are specific to the crypto factory.
*
* @return Default crypto suite.
* @throws IllegalAccessException
* @throws InstantiationException
* @throws ClassNotFoundException
* @throws CryptoException
* @throws InvalidArgumentException
* @throws NoSuchMethodException
* @throws InvocationTargetException
*/
public static CryptoSuite getCryptoSuite() throws IllegalAccessException, InstantiationException,
ClassNotFoundException, CryptoException, InvalidArgumentException, NoSuchMethodException,
InvocationTargetException {
return CryptoSuiteFactory.getDefault().getCryptoSuite();
}
/**
* Get a crypto suite with the default factory with settings defined by properties
* Properties are uniquely defined by the specific crypto factory.
*
* @param properties properties that define suite characteristics such as strength, curve, hashing .
* @return
* @throws IllegalAccessException
* @throws InstantiationException
* @throws ClassNotFoundException
* @throws CryptoException
* @throws InvalidArgumentException
* @throws NoSuchMethodException
* @throws InvocationTargetException
*/
public static CryptoSuite getCryptoSuite(Properties properties) throws IllegalAccessException, InstantiationException,
ClassNotFoundException, CryptoException, InvalidArgumentException, NoSuchMethodException,
InvocationTargetException {
return CryptoSuiteFactory.getDefault().getCryptoSuite(properties);
}
}
}

View File

@ -1,82 +0,0 @@
/*
*
* Copyright 2016,2017 DTCC, Fujitsu Australia Software Technology, IBM - All Rights Reserved.
*
* 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 com.chinaunicom.mall.ebtp.common.crypto.security;
import com.chinaunicom.mall.ebtp.common.crypto.exception.CryptoException;
import com.chinaunicom.mall.ebtp.common.crypto.exception.InvalidArgumentException;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;
/**
* Factory to produce a set of crypto suite implementations offering differing cryptographic algorithms and strengths.
*/
public interface CryptoSuiteFactory {
/**
* If set as the default security provider then default crypto suite will not use explicit
* provider
*/
String DEFAULT_JDK_PROVIDER = "org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.security.default_jdk_provider";
/**
* Produce a crypto suite by specified by these properties.
* Properties are unique to each Crypto Suite implementation.
*
* @param properties
* @return
* @throws CryptoException
* @throws InvalidArgumentException
*/
CryptoSuite getCryptoSuite(Properties properties) throws CryptoException, InvalidArgumentException;
/**
* Return a default crypto suite
*
* @return
* @throws CryptoException
* @throws InvalidArgumentException
*/
CryptoSuite getCryptoSuite() throws CryptoException, InvalidArgumentException;
/**
* This will return the default Crypto Suite Factory implementation.
* Can be overwritten by org.hyperledger.fabric.com.chinaunicom.ebtp.mall.cloud.attachment.sdk.crypto.default_crypto_suite_factory property.
* see
* Classes specified by this property must implement a public static method <b>instance</b> that
* returns back a single instance of this factory.
*
* @return A single instance of a CryptoSuiteFactory.
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws NoSuchMethodException
* @throws InvocationTargetException
*/
static CryptoSuiteFactory getDefault() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
return HLSDKJCryptoSuiteFactory.getDefault();
}
}

View File

@ -1,120 +0,0 @@
/*
* Copyright 2016,2017 DTCC, Fujitsu Australia Software Technology, IBM - All Rights Reserved.
*
* 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 com.chinaunicom.mall.ebtp.common.crypto.security;
import com.chinaunicom.mall.ebtp.common.crypto.exception.CryptoException;
import com.chinaunicom.mall.ebtp.common.crypto.exception.InvalidArgumentException;
import com.chinaunicom.mall.ebtp.common.crypto.helper.Config;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
/**
* SDK's Default implementation of CryptoSuiteFactory.
*/
public class HLSDKJCryptoSuiteFactory implements CryptoSuiteFactory {
private static final Config config = Config.getConfig();
private static final int SECURITY_LEVEL = config.getSecurityLevel();
private static final String HASH_ALGORITHM = config.getHashAlgorithm();
private HLSDKJCryptoSuiteFactory() {
}
private static final Map<Properties, CryptoSuite> cache = new ConcurrentHashMap<>();
@Override
public CryptoSuite getCryptoSuite(Properties properties) throws CryptoException, InvalidArgumentException {
CryptoSuite ret = cache.get(properties);
if (ret == null) {
try {
CryptoPrimitives cp = new CryptoPrimitives();
cp.setProperties(properties);
cp.init();
ret = cp;
} catch (Exception e) {
throw new CryptoException(e.getMessage(), e);
}
cache.put(properties, ret);
}
return ret;
}
@Override
public CryptoSuite getCryptoSuite() throws CryptoException, InvalidArgumentException {
Properties properties = new Properties();
properties.put(Config.SECURITY_LEVEL, SECURITY_LEVEL);
properties.put(Config.HASH_ALGORITHM, HASH_ALGORITHM);
return getCryptoSuite(properties);
}
private static final HLSDKJCryptoSuiteFactory INSTANCE = new HLSDKJCryptoSuiteFactory();
static synchronized HLSDKJCryptoSuiteFactory instance() {
return INSTANCE;
}
private static CryptoSuiteFactory theFACTORY = null; // one and only factory.
static final synchronized CryptoSuiteFactory getDefault() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
if (null == theFACTORY) {
String cf = config.getDefaultCryptoSuiteFactory();
if (null == cf || cf.isEmpty() || cf.equals(HLSDKJCryptoSuiteFactory.class.getName())) { // Use this class as the factory.
theFACTORY = HLSDKJCryptoSuiteFactory.instance();
} else {
// Invoke static method instance on factory class specified by config properties.
// In this case this class will no longer be used as the factory.
Class<?> aClass = Class.forName(cf);
Method method = aClass.getMethod("instance");
Object theFACTORYObject = method.invoke(null);
if (null == theFACTORYObject) {
throw new InstantiationException(String.format("Class specified by %s has instance method returning null. Expected object implementing CryptoSuiteFactory interface.", cf));
}
if (!(theFACTORYObject instanceof CryptoSuiteFactory)) {
throw new InstantiationException(String.format("Class specified by %s has instance method returning a class %s which does not implement interface CryptoSuiteFactory ",
cf, theFACTORYObject.getClass().getName()));
}
theFACTORY = (CryptoSuiteFactory) theFACTORYObject;
}
}
return theFACTORY;
}
}

View File

@ -1,244 +0,0 @@
package com.chinaunicom.mall.ebtp.common.crypto.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.chinaunicom.mall.ebtp.common.crypto.exception.InvalidArgumentException;
import com.chinaunicom.mall.ebtp.common.crypto.security.CryptoPrimitives;
import com.chinaunicom.mall.ebtp.common.crypto.tenderfee.test;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.util.encoders.Base64;
import java.io.*;
import java.net.URL;
import java.security.PrivateKey;
@Slf4j
public class CrypServiceImpl {
private static final String SIGNING_ALGORITHM = "SHA256withECDSA";
private static final String DATA_PATH = "C:\\Users\\user\\Downloads\\debian-edu-10.8.0-amd64-netinst.iso.torrent";
// 私钥文件路径 - 加密
private static String PEM_PATH = "admin_certPrivate.pem";
// 证书文件路径 - 解密
private static String CRT_PATH = "admin.crt";
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, CryptoException, InvalidArgumentException, UnsupportedEncodingException {
URL pem = test.class.getClassLoader().getResource(PEM_PATH);
URL crt = test.class.getClassLoader().getResource(CRT_PATH);
PEM_PATH = pem.getPath();
CRT_PATH = crt.getPath();
// example of HashMap entity, treeMap can also work out,
// but LinkedHashMap is NOT supported
// Map<String,String> map = new HashMap<>(1);
// map.put("SECTION_ID","L3307");
// map.put("DOCUMENT_ID","8533");
// map.put("CONTENT_FILE_HASH","12321123");
// map.put("TP_ID","L3307A");
//
// String signature = signObject(map,PEM_PATH);
// System.out.println("signature of Map: "+signature);
// boolean isOk = verifyObject(signature,map,CRT_PATH);
// System.out.println("verify result of Map: "+ isOk);
// example of bean entity
String pemVal = "-----BEGIN PRIVATE KEY-----\n" +
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgjF+tq8oc1tNjot69\n" +
"9OQgzr7Dqg1OkVo4PY4tKBL8+82hRANCAARKLIuOloTZe1B0J0k+CITZdsx8Gham\n" +
"JTuxCRGLdCLpq6wHHGEqWn9VDkwk5eX6OYQxYuBRiPZp7gP/njpx5CkF\n" +
"-----END PRIVATE KEY-----";
String crtVal = "-----BEGIN CERTIFICATE-----\n" +
"MIICgzCCAimgAwIBAgIULDLuWrkCL3UaWO5u7yiu8UghEjEwCgYIKoZIzj0EAwIw\n" +
"ZzELMAkGA1UEBhMCQ04xETAPBgNVBAgTCFNoYW5Eb25nMQ4wDAYDVQQHEwVKaU5h\n" +
"bjEYMBYGA1UEChMPYWRtaW50MDgxMmFvcmczMRswGQYDVQQDExJjYS5hZG1pbnQw\n" +
"ODEyYW9yZzMwHhcNMjEwODE3MDExODAwWhcNMjIwODE3MDEyMzAwWjAzMRwwDQYD\n" +
"VQQLEwZjbGllbnQwCwYDVQQLEwRvcmczMRMwEQYDVQQDDAphZG1pbkBvcmczMFkw\n" +
"EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESiyLjpaE2XtQdCdJPgiE2XbMfBoWpiU7\n" +
"sQkRi3Qi6ausBxxhKlp/VQ5MJOXl+jmEMWLgUYj2ae4D/546ceQpBaOB5jCB4zAO\n" +
"BgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUcyAwVSk9V615\n" +
"ryVrpykYwJbUs7UwKwYDVR0jBCQwIoAgOIS8Yvvj2hRg0V3+x659Mn60B09bt8Fl\n" +
"eRcf79zjGRkwFAYDVR0RBA0wC4IJSlpaSEpTLTcyMGEGCCoDBAUGBwgBBFV7ImF0\n" +
"dHJzIjp7ImhmLkFmZmlsaWF0aW9uIjoib3JnMyIsImhmLkVucm9sbG1lbnRJRCI6\n" +
"ImFkbWluQG9yZzMiLCJoZi5UeXBlIjoiY2xpZW50In19MAoGCCqGSM49BAMCA0gA\n" +
"MEUCIQCi/6V6gmt4k5MUSfym9RFGqPwmD1hyWmtWKj448PXALAIgQfHHiX+P2M6k\n" +
"GqneZYuHHxazU37s5ZaFBPylOJJEO2Y=\n" +
"-----END CERTIFICATE-----";
// 需正确设置bean的@JSONField以确保解析到的字段名称与文档一致
// List<BidTenderFeeBaseParam> paramList = new ArrayList<>();
// BidTenderFeeBaseParam bean = new BidTenderFeeBaseParam();
// bean.setTenderId("8533");
// bean.setShoppingCartId("L3307");
// bean.setAmount("1000");
// bean.setTpId("L3307A");
// bean.setSectionId("1111");
// paramList.add(bean);
// // 用于签名的Bean将被signObject转换为json(String,然后转换为byte[]),请确保该json只包含文档规定的业务字段且“SGIN"不应包含其中
// String signatureOfBean = signObject2(paramList,pemVal);
// // 生成的签名现在可以追加到签名字段
// System.out.println("signature of Bean: "+signatureOfBean);
// boolean isOkBean = verifyValue(signatureOfBean,paramList,crtVal);
// System.out.println("verify result of Bean: "+ isOkBean);
}
/**
* 验证数据实体
*
* @param signatureString Base64加密的密钥
* @param entity 数据实体
* @param crtKey 证书路径
* @return
*/
public static boolean verifyValue(String signatureString, Object entity, String crtKey) {
return verifyValue(signatureString, JSON.toJSONBytes(entity, SerializerFeature.MapSortField, SerializerFeature.SortField), crtKey);
}
/**
* 验证二进制数据串
*
* @param signatureString Base64加密的密钥
* @param plainData 源数据
* @param crtKey 证书路径
* @return
*/
public static boolean verifyValue(String signatureString, byte[] plainData, String crtKey) {
byte[] signature = Base64.decode(signatureString);
CryptoPrimitives cp = null;
boolean result = false;
try {
cp = new CryptoPrimitives();
cp.init();
byte[] crtBytes = crtKey.getBytes();
result = cp.verify(crtBytes, SIGNING_ALGORITHM, signature, plainData);
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | InvalidArgumentException | com.chinaunicom.mall.ebtp.common.crypto.exception.CryptoException e) {
e.printStackTrace();
}
return result;
}
/**
* 验证二进制数据串
*
* @param signatureString Base64加密的密钥
* @param plainData 源数据
* @param crtPath 证书路径
* @return
*/
public static boolean verifyBytes(String signatureString, byte[] plainData, String crtPath) {
byte[] signature = Base64.decode(signatureString);
CryptoPrimitives cp = null;
boolean result = false;
try {
cp = new CryptoPrimitives();
cp.init();
byte[] crtBytes = readAsBytes(crtPath);
result = cp.verify(crtBytes, SIGNING_ALGORITHM, signature, plainData);
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | InvalidArgumentException | com.chinaunicom.mall.ebtp.common.crypto.exception.CryptoException e) {
e.printStackTrace();
}
return result;
}
/**
* 验证数据实体
*
* @param signatureString Base64加密的密钥
* @param entity 数据实体
* @return
*/
public static boolean verifyObject(String signatureString, Object entity) {
URL crt = test.class.getClassLoader().getResource(CRT_PATH);
return verifyObject(signatureString, entity, crt.getPath());
}
/**
* 验证数据实体
*
* @param signatureString Base64加密的密钥
* @param entity 数据实体
* @param crtPath 证书路径
* @return
*/
public static boolean verifyObject(String signatureString, Object entity, String crtPath) {
return verifyBytes(signatureString, JSON.toJSONBytes(entity, SerializerFeature.MapSortField, SerializerFeature.SortField), crtPath);
}
/**
* 生成签名
*
* @param object 数据实体
* @return Base64加密的密钥
*/
public static String signObject(Object object) {
URL pem = test.class.getClassLoader().getResource(PEM_PATH);
return signObject(object, pem.getPath());
}
/**
* 生成签名
*
* @param object 数据实体
* @param privateVal 密钥路径
* @return Base64加密的密钥
*/
public static String signObject2(Object object, String privateVal) {
CryptoPrimitives cp = null;
byte[] signature = null;
try {
cp = new CryptoPrimitives();
cp.init();
byte[] pemBytes = privateVal.getBytes();
PrivateKey key = cp.bytesToPrivateKey(pemBytes);
signature = cp.sign(key, JSON.toJSONBytes(object, SerializerFeature.MapSortField, SerializerFeature.SortField));
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | InvalidArgumentException | com.chinaunicom.mall.ebtp.common.crypto.exception.CryptoException e) {
e.printStackTrace();
}
return signature == null ? "" : Base64.toBase64String(signature);
}
/**
* 生成签名
*
* @param object 数据实体
* @param privatePath 密钥路径
* @return Base64加密的密钥
*/
public static String signObject(Object object, String privatePath) {
CryptoPrimitives cp = null;
byte[] signature = null;
try {
cp = new CryptoPrimitives();
cp.init();
byte[] pemBytes = readAsBytes(privatePath);
PrivateKey key = cp.bytesToPrivateKey(pemBytes);
signature = cp.sign(key, JSON.toJSONBytes(object, SerializerFeature.MapSortField, SerializerFeature.SortField));
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | InvalidArgumentException | com.chinaunicom.mall.ebtp.common.crypto.exception.CryptoException e) {
e.printStackTrace();
}
return signature == null ? "" : Base64.toBase64String(signature);
}
private static byte[] readAsBytes(String path) {
File file = new File(path);
byte[] result = {};
try (FileInputStream is = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(is);) {
result = IOUtils.toByteArray(bis);
} catch (FileNotFoundException e) {
log.error(path + " not found");
} catch (IOException e) {
log.error(e.toString());
}
return result;
}
}

View File

@ -1,62 +0,0 @@
package com.chinaunicom.mall.ebtp.common.crypto.tenderfee;
import com.chinaunicom.mall.ebtp.common.crypto.exception.InvalidArgumentException;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.CryptoException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
@Slf4j
public class test {
// 私钥文件路径 - 加密
private static String PEM_PATH = "admin_certPrivate.pem";
// 证书文件路径 - 解密
private static String CRT_PATH = "admin.crt";
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, CryptoException, InvalidArgumentException, UnsupportedEncodingException {
//String token = AccessToken.tokenCreate();
URL pem = test.class.getClassLoader().getResource(PEM_PATH);
URL crt = test.class.getClassLoader().getResource(CRT_PATH);
PEM_PATH = pem.getPath();
CRT_PATH = crt.getPath();
// example of bean entity
String pemVal = "-----BEGIN PRIVATE KEY-----\n" +
"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgjF+tq8oc1tNjot69\n" +
"9OQgzr7Dqg1OkVo4PY4tKBL8+82hRANCAARKLIuOloTZe1B0J0k+CITZdsx8Gham\n" +
"JTuxCRGLdCLpq6wHHGEqWn9VDkwk5eX6OYQxYuBRiPZp7gP/njpx5CkF\n" +
"-----END PRIVATE KEY-----";
// 需正确设置bean的@JSONField以确保解析到的字段名称与文档一致
// List<BidTenderFeeBaseParam> paramList = new ArrayList<>();
// BidTenderFeeBaseParam bean = new BidTenderFeeBaseParam();
// bean.setTenderId("8533");
// bean.setShoppingCartId("L3307");
// bean.setAmount("1000");
// bean.setTpId("L3307A");
// bean.setSectionId("1111");
//
// paramList.add(bean);
// // 用于签名的Bean将被signObject转换为json(String,然后转换为byte[]),请确保该json只包含文档规定的业务字段且“SGIN"不应包含其中
// String signatureOfBean = CrypServiceImpl.signObject2(paramList,pemVal);//CrypService.signObject(paramList);
// System.out.println("signature of Bean: "+signatureOfBean);
// boolean isOkBean = CrypServiceImpl.verifyObject(signatureOfBean,paramList);
// System.out.println("verify result of Bean: "+ isOkBean);
// String signatureOfBean = signObject(paramList,PEM_PATH);
// // 生成的签名现在可以追加到签名字段
// System.out.println("signature of Bean: "+signatureOfBean);
// boolean isOkBean = verifyObject(signatureOfBean,paramList,CRT_PATH);
// System.out.println("verify result of Bean: "+ isOkBean);
}
}