请求携带 证书序列号
parent
b09bec5c2b
commit
6063c84f32
|
|
@ -17,6 +17,11 @@ public final class Constants {
|
|||
public static final String APP_NO = "X-SCFS-App-No";
|
||||
public static final String SIGNATURE = "X-SCFS-Signature";
|
||||
public static final String API_VERSION = "X-SCFS-Api-Version";
|
||||
// 银行侧证书编号
|
||||
public static final String BANK_CERTIFICATE_SERIAL = "X-SCFS-Serial";
|
||||
|
||||
// 渠道侧证书编号
|
||||
public static final String CHANNEL_CERTIFICATE_SERIAL = "X-SCFS-Channel-Serial";
|
||||
// http 自定义字段
|
||||
public static final String TIMESTAMP = "X-SCFS-Timestamp";
|
||||
public static final String NONCE = "X-SCFS-Nonce";
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ public abstract class AbstractPrivacyEncryptor implements PrivacyEncryptor {
|
|||
protected final String transformation;
|
||||
protected final PublicKey publicKey;
|
||||
protected final Provider provider;
|
||||
private final String certificateSerial;
|
||||
|
||||
/**
|
||||
* 构造敏感信息加密的抽象类
|
||||
|
|
@ -31,10 +32,11 @@ public abstract class AbstractPrivacyEncryptor implements PrivacyEncryptor {
|
|||
* @param publicKey 加密使用的公钥
|
||||
* @param provider 安全库提供商
|
||||
*/
|
||||
protected AbstractPrivacyEncryptor(String transformation, PublicKey publicKey, Provider provider) {
|
||||
protected AbstractPrivacyEncryptor(String transformation, PublicKey publicKey, Provider provider, String certificateSerial) {
|
||||
this.transformation = requireNonNull(transformation);
|
||||
this.publicKey = requireNonNull(publicKey);
|
||||
this.provider = provider;
|
||||
this.certificateSerial = certificateSerial;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -76,4 +78,9 @@ public abstract class AbstractPrivacyEncryptor implements PrivacyEncryptor {
|
|||
public PublicKey getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCertificateSerial() {
|
||||
return certificateSerial;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ public abstract class AbstractSigner implements Signer {
|
|||
protected final String algorithmName;
|
||||
protected final PrivateKey privateKey;
|
||||
protected final Provider provider;
|
||||
private final String certificateSerial;
|
||||
|
||||
/**
|
||||
* AbstractSigner 构造函数
|
||||
|
|
@ -27,11 +28,12 @@ public abstract class AbstractSigner implements Signer {
|
|||
* @param algorithmName 获取Signature对象时指定的算法,例如SHA256withRSA
|
||||
* @param privateKey API私钥
|
||||
*/
|
||||
protected AbstractSigner(String algorithm, String algorithmName, PrivateKey privateKey, Provider provider) {
|
||||
protected AbstractSigner(String algorithm, String algorithmName, PrivateKey privateKey, Provider provider, String certificateSerial) {
|
||||
this.algorithm = requireNonNull(algorithm);
|
||||
this.algorithmName = requireNonNull(algorithmName);
|
||||
this.privateKey = requireNonNull(privateKey);
|
||||
this.provider = provider;
|
||||
this.certificateSerial = requireNonNull(certificateSerial);
|
||||
}
|
||||
|
||||
private java.security.Signature getSignature() {
|
||||
|
|
@ -51,7 +53,7 @@ public abstract class AbstractSigner implements Signer {
|
|||
java.security.Signature signature = getSignature();
|
||||
signature.initSign(privateKey);
|
||||
signature.update(Strings.toBytes(message));
|
||||
return new SignatureResult(Base64.encodeStr(signature.sign()));
|
||||
return new SignatureResult(getCertificateSerial(), Base64.encodeStr(signature.sign()));
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new IllegalArgumentException(algorithm + " signature uses an illegal privateKey.", e);
|
||||
} catch (SignatureException e) {
|
||||
|
|
@ -59,6 +61,11 @@ public abstract class AbstractSigner implements Signer {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCertificateSerial() {
|
||||
return certificateSerial;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ public abstract class AbstractVerifier implements Verifier {
|
|||
|
||||
@Override
|
||||
public boolean verify(String serialNumber, String message, String signature) {
|
||||
X509Certificate certificate = certificateProvider.getAvailableCertificate();
|
||||
X509Certificate certificate = certificateProvider.getCertificate(serialNumber);
|
||||
if (certificate == null) {
|
||||
logger.error("校验证书不存在");
|
||||
logger.error("校验证书不存在, 证书序列号: {}", serialNumber);
|
||||
return false;
|
||||
}
|
||||
return verify(certificate, message, signature);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.czcb.scfs.api.core.cipher;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.cert.CertificateExpiredException;
|
||||
import java.security.cert.CertificateNotYetValidException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
|
@ -14,13 +13,13 @@ import java.util.Map;
|
|||
*/
|
||||
public class CertificateValidity {
|
||||
|
||||
public X509Certificate getLongestCertificate(Map<BigInteger, X509Certificate> certificates) {
|
||||
public X509Certificate getLongestCertificate(Map<String, X509Certificate> certificates) {
|
||||
if (certificates == null || certificates.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
X509Certificate longest = null;
|
||||
for (Map.Entry<BigInteger, X509Certificate> item : certificates.entrySet()) {
|
||||
for (Map.Entry<String, X509Certificate> item : certificates.entrySet()) {
|
||||
if (longest == null || item.getValue().getNotAfter().after(longest.getNotAfter())) {
|
||||
longest = item.getValue();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,17 +26,18 @@ public class DefaultCredential implements Credential {
|
|||
@Override
|
||||
public String buildRequestAuthorization(HttpRequest request, Channel channel) {
|
||||
// 添加请求必要头部
|
||||
addNecessityCustomizeHeaders(request);
|
||||
addNecessityCustomizeHeaders(signer, request);
|
||||
// 认证串
|
||||
return String.format("SCFS-%s %s", signer.getAlgorithm(), authText(channel, buildRequestSignature(request)));
|
||||
return String.format("SCFS-%s %s", signer.getAlgorithm(), authorizationMessage(channel, buildRequestSignature(request)));
|
||||
}
|
||||
|
||||
private void addNecessityCustomizeHeaders(HttpRequest request) {
|
||||
private void addNecessityCustomizeHeaders(Signer signer, HttpRequest request) {
|
||||
request.getHttpHeaders().addHeader(CHANNEL_CERTIFICATE_SERIAL, signer.getCertificateSerial());
|
||||
request.getHttpHeaders().addHeader(NONCE, request.getId());
|
||||
request.getHttpHeaders().addHeader(TIMESTAMP, DateTimes.ofTimestamp());
|
||||
}
|
||||
|
||||
private String buildRequestSignature(HttpRequest request) {
|
||||
private SignatureResult buildRequestSignature(HttpRequest request) {
|
||||
// 签名头 X-SCFS-Nonce=xx,X-SCFS-Timestamp=xxx,X-SCFS-Secret-Key=xx
|
||||
String signatureHeader = getSignatureHeader(request.getHttpHeaders());
|
||||
// 请求方法GET/POST,需要大写
|
||||
|
|
@ -48,14 +49,16 @@ public class DefaultCredential implements Credential {
|
|||
// 构建待签名串
|
||||
String message = buildRequestMessage(signatureHeader, method, url, body);
|
||||
// 私钥加签
|
||||
return signer.sign(message).getResult();
|
||||
return signer.sign(message);
|
||||
}
|
||||
|
||||
private String getSignatureHeader(HttpHeaders httpHeaders) {
|
||||
Map<String, String> headers = httpHeaders.getHeaders();
|
||||
return NONCE + "=" + headers.get(NONCE) + "," +
|
||||
TIMESTAMP + "=" + headers.get(TIMESTAMP) + "," +
|
||||
SECRET_KEY + "=" + headers.get(SECRET_KEY);
|
||||
return NONCE + "=" + Strings.fmtEmpty(headers.get(NONCE)) + "," +
|
||||
TIMESTAMP + "=" + Strings.fmtEmpty(headers.get(TIMESTAMP)) + "," +
|
||||
BANK_CERTIFICATE_SERIAL + "=" + Strings.fmtEmpty(httpHeaders.getHeader(BANK_CERTIFICATE_SERIAL)) + "," +
|
||||
CHANNEL_CERTIFICATE_SERIAL + "=" + Strings.fmtEmpty(httpHeaders.getHeader(CHANNEL_CERTIFICATE_SERIAL)) + "," +
|
||||
SECRET_KEY + "=" + Strings.fmtEmpty(headers.get(SECRET_KEY));
|
||||
}
|
||||
|
||||
private String getSignatureBody(HttpRequest request) {
|
||||
|
|
@ -72,11 +75,11 @@ public class DefaultCredential implements Credential {
|
|||
requestBody + "\n";
|
||||
}
|
||||
|
||||
private String authText(Channel channel, String signature) {
|
||||
private String authorizationMessage(Channel channel, SignatureResult result) {
|
||||
// 认证串
|
||||
return CHANNEL_NO + "=" + channel.getChannelNo() + "," +
|
||||
APP_NO + "=" + channel.getAppNo() + "," +
|
||||
SIGNATURE + "=" + signature;
|
||||
SIGNATURE + "=" + result.getSignature();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@ public final class DefaultValidator implements Validator {
|
|||
// 校验时间戳
|
||||
validateTimestamp(request, response);
|
||||
|
||||
// 请求头包含 SecretKey 进行验签
|
||||
if (!headerContainsSecretKey(response)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -80,7 +79,9 @@ public final class DefaultValidator implements Validator {
|
|||
response.getHttpHeaders().getHeader(REQUEST_ID)));
|
||||
}
|
||||
|
||||
if (!verifier.verify(null, message, signature)) {
|
||||
// 签名证书编号
|
||||
String serialNumber = response.getHttpHeaders().getHeader(BANK_CERTIFICATE_SERIAL);
|
||||
if (!verifier.verify(serialNumber, message, signature)) {
|
||||
httpLogger.logResponseError(request, response);
|
||||
throw new ValidationException(String.format("响应校验失败, 签名校验未通过, Request-Id=%s",
|
||||
response.getHttpHeaders().getHeader(REQUEST_ID)));
|
||||
|
|
@ -91,6 +92,8 @@ public final class DefaultValidator implements Validator {
|
|||
}
|
||||
|
||||
private boolean headerContainsSecretKey(OriginalResponse response) {
|
||||
return Strings.isNotEmpty(response.getHttpHeaders().getHeader(SECRET_KEY));
|
||||
return Strings.isNotEmpty(response.getHttpHeaders().getHeader(SECRET_KEY))
|
||||
&& Strings.isNotEmpty(response.getHttpHeaders().getHeader(CHANNEL_CERTIFICATE_SERIAL))
|
||||
&& Strings.isNotEmpty(response.getHttpHeaders().getHeader(BANK_CERTIFICATE_SERIAL));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
package com.czcb.scfs.api.core.cipher;
|
||||
|
||||
import com.czcb.scfs.api.core.util.DateTimes;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static com.czcb.scfs.api.core.Constants.HEX;
|
||||
import static com.czcb.scfs.api.core.util.Strings.timeRange;
|
||||
import static com.czcb.scfs.api.core.util.Strings.toHexUpper;
|
||||
|
||||
/**
|
||||
* 证书提供器的简单实现,证书存储在内存ConcurrentHashMap中
|
||||
|
|
@ -19,7 +18,7 @@ import static com.czcb.scfs.api.core.Constants.HEX;
|
|||
public final class LocalCertificateProvider implements CertificateProvider {
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final ConcurrentHashMap<BigInteger, X509Certificate> certificates = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, X509Certificate> certificates = new ConcurrentHashMap<>();
|
||||
// 证书有效期校验
|
||||
private final CertificateValidity validity = new CertificateValidity();
|
||||
private X509Certificate availableCertificate;
|
||||
|
|
@ -40,22 +39,16 @@ public final class LocalCertificateProvider implements CertificateProvider {
|
|||
*/
|
||||
@Override
|
||||
public X509Certificate getCertificate(String serialNumber) {
|
||||
BigInteger key = new BigInteger(serialNumber, HEX);
|
||||
return certificates.get(key);
|
||||
return certificates.get(serialNumber);
|
||||
}
|
||||
|
||||
public void addX509Certificate(X509Certificate certificate) {
|
||||
if (!validity.withinValidity(certificate)) {
|
||||
logger.error("证书已失效, 序列号:{}, 有效范围:[{}]", certificate.getSerialNumber(), timeRange(certificate));
|
||||
logger.error("证书已失效, 序列号:{}, 有效范围:[{}]", toHexUpper(certificate.getSerialNumber()), timeRange(certificate));
|
||||
return;
|
||||
}
|
||||
|
||||
certificates.put(certificate.getSerialNumber(), certificate);
|
||||
}
|
||||
|
||||
private String timeRange(X509Certificate certificate) {
|
||||
return String.format("%s,%s", DateTimes.ofPatternDate(certificate.getNotBefore()),
|
||||
DateTimes.ofPatternDate(certificate.getNotAfter()));
|
||||
certificates.put(toHexUpper(certificate.getSerialNumber()), certificate);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -23,4 +23,6 @@ public interface PrivacyEncryptor {
|
|||
* @return PublicKey
|
||||
*/
|
||||
PublicKey getPublicKey();
|
||||
|
||||
String getCertificateSerial();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,18 +10,27 @@ import static java.util.Objects.requireNonNull;
|
|||
* @since 2.0.0
|
||||
*/
|
||||
public class SignatureResult {
|
||||
private final String certificateSerial;
|
||||
private final String signature;
|
||||
|
||||
public SignatureResult(String signature) {
|
||||
public SignatureResult(String certificateSerial, String signature) {
|
||||
this.certificateSerial = certificateSerial;
|
||||
this.signature = requireNonNull(signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 渠道对应的证书序列号
|
||||
*/
|
||||
public String getCertificateSerial() {
|
||||
return certificateSerial;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取签名
|
||||
*
|
||||
* @return 签名
|
||||
*/
|
||||
public String getResult() {
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ public interface Signer {
|
|||
*/
|
||||
SignatureResult sign(String message);
|
||||
|
||||
String getCertificateSerial();
|
||||
|
||||
/**
|
||||
* 获取签名算法
|
||||
*
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@ public interface Verifier {
|
|||
* @return 是否验证通过
|
||||
*/
|
||||
boolean verify(String serialNumber, String message, String signature);
|
||||
}
|
||||
}
|
||||
|
|
@ -139,9 +139,12 @@ public abstract class AbstractApiClient implements ApiClient {
|
|||
// 生成密钥
|
||||
byte[] secretKey = cipher.getSecretKey();
|
||||
// 密钥进行非对称加密
|
||||
String encryptSecretKey = privacy.getEncryptor().encrypt(Strings.toStr(secretKey));
|
||||
PrivacyEncryptor encryptor = privacy.getEncryptor();
|
||||
String encryptSecretKey = encryptor.encrypt(Strings.toStr(secretKey));
|
||||
// 加密后的密钥放入到请求头
|
||||
httpRequest.getHttpHeaders().addHeader(SECRET_KEY, encryptSecretKey);
|
||||
// 加密证书序列号
|
||||
httpRequest.getHttpHeaders().addHeader(BANK_CERTIFICATE_SERIAL, encryptor.getCertificateSerial());
|
||||
|
||||
// 原始body
|
||||
byte[] originalBody = httpRequest.getRequestBody().getBody();
|
||||
|
|
|
|||
|
|
@ -2,12 +2,16 @@ package com.czcb.scfs.api.core.util;
|
|||
|
||||
import com.czcb.scfs.api.core.exception.EncodingException;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
|
||||
import static com.czcb.scfs.api.core.Constants.HEX;
|
||||
|
||||
/**
|
||||
* @author wangwei
|
||||
* @since 2.0.0
|
||||
|
|
@ -93,4 +97,21 @@ public class Strings {
|
|||
throw new EncodingException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String fmtEmpty(String text) {
|
||||
return Strings.isEmpty(text) ? "" : text;
|
||||
}
|
||||
|
||||
public static String toHexUpper(BigInteger data) {
|
||||
return data.toString(HEX).toUpperCase();
|
||||
}
|
||||
|
||||
public static String toUpper(String data) {
|
||||
return data.toUpperCase();
|
||||
}
|
||||
|
||||
public static String timeRange(X509Certificate certificate) {
|
||||
return String.format("%s,%s", DateTimes.ofPatternDate(certificate.getNotBefore()),
|
||||
DateTimes.ofPatternDate(certificate.getNotAfter()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class AbstractPrivacyEncryptorTest {
|
|||
|
||||
private static class TestPrivacyEncryptorv2 extends AbstractPrivacyEncryptor {
|
||||
public TestPrivacyEncryptorv2(PublicKey publicKey, Provider provider) {
|
||||
super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, provider);
|
||||
super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, provider, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ class AbstractSignerTest {
|
|||
void sign() {
|
||||
TestSigner signer = new TestSigner(KeyText.loadTestPrivateKeyRSA(), null);
|
||||
String message = "1234567890";
|
||||
String sg = signer.sign(message).getResult();
|
||||
String sg = signer.sign(message).getSignature();
|
||||
Assertions.assertNotNull(sg);
|
||||
Assertions.assertEquals("SHA256withRSA", signer.getAlgorithm());
|
||||
|
||||
|
|
@ -41,12 +41,12 @@ class AbstractSignerTest {
|
|||
* @param privateKey API私钥
|
||||
*/
|
||||
public TestSigner(PrivateKey privateKey, Provider provider) {
|
||||
super("SHA256withRSA", "SHA256withRSA", privateKey, provider);
|
||||
super("SHA256withRSA", "SHA256withRSA", privateKey, provider, "");
|
||||
}
|
||||
|
||||
public TestSigner(PrivateKey privateKey) {
|
||||
// 错误的签名算法
|
||||
super("SHA256withRSA1", "SHA256withRSA1", privateKey, null);
|
||||
super("SHA256withRSA1", "SHA256withRSA1", privateKey, null, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@ import com.czcb.scfs.api.core.util.PemFile;
|
|||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
|
@ -64,9 +63,9 @@ class CertificateValidityTest {
|
|||
Assertions.assertNull(validity.getLongestCertificate(null));
|
||||
Assertions.assertNull(validity.getLongestCertificate(new HashMap<>()));
|
||||
|
||||
ConcurrentHashMap<BigInteger, X509Certificate> certificates = new ConcurrentHashMap<>();
|
||||
ConcurrentHashMap<String, X509Certificate> certificates = new ConcurrentHashMap<>();
|
||||
X509Certificate certificate = KeyText.loadTestRSA();
|
||||
certificates.put(certificate.getSerialNumber(), certificate);
|
||||
certificates.put(certificate.getSerialNumber().toString(), certificate);
|
||||
Assertions.assertNotNull(validity.getLongestCertificate(certificates));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ class SignatureResultTest {
|
|||
|
||||
@Test
|
||||
void getResult() {
|
||||
SignatureResult result = new SignatureResult("123456");
|
||||
Assertions.assertEquals("123456", result.getResult());
|
||||
SignatureResult result = new SignatureResult("", "123456");
|
||||
Assertions.assertEquals("123456", result.getSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToString() {
|
||||
SignatureResult result = new SignatureResult("123456");
|
||||
SignatureResult result = new SignatureResult("", "123456");
|
||||
Assertions.assertEquals("{\"signature\":\"123456\"}", result.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ class ApacheHttpclientProxyTest {
|
|||
SECRET_KEY + "=" + secretKey;
|
||||
|
||||
String message = buildAuth + "\n" + responseBody + "\n";
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getResult());
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getSignature());
|
||||
|
||||
client.when(request()
|
||||
.withMethod(HttpMethod.POST.getUpperName())
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class ApacheHttpclientTest {
|
|||
SECRET_KEY + "=" + secretKey;
|
||||
|
||||
String message = buildAuth + "\n" + responseBody + "\n";
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getResult());
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getSignature());
|
||||
|
||||
client.when(request()
|
||||
.withMethod(HttpMethod.POST.getUpperName())
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class ApacheHttpclientTestProxyTest {
|
|||
SECRET_KEY + "=" + secretKey;
|
||||
|
||||
String message = buildAuth + "\n" + responseBody + "\n";
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getResult());
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getSignature());
|
||||
|
||||
client.when(request()
|
||||
.withMethod(HttpMethod.POST.getUpperName())
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class ApacheHttpclientV2Test {
|
|||
SECRET_KEY + "=" + secretKey;
|
||||
|
||||
String message = buildAuth + "\n" + "\n";
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getResult());
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getSignature());
|
||||
|
||||
client.when(request()
|
||||
.withMethod(HttpMethod.POST.getUpperName())
|
||||
|
|
@ -129,7 +129,7 @@ class ApacheHttpclientV2Test {
|
|||
SECRET_KEY + "=" + secretKey;
|
||||
|
||||
String message = buildAuth + "\n" + responseBody + "\n";
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getResult());
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getSignature());
|
||||
|
||||
client.when(request()
|
||||
.withMethod(HttpMethod.GET.getUpperName())
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class ApacheHttpclientV3Test {
|
|||
SECRET_KEY + "=" + secretKey;
|
||||
|
||||
String message = buildAuth + "\n" + "\n";
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getResult());
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getSignature());
|
||||
|
||||
client.when(request()
|
||||
.withMethod(HttpMethod.POST.getUpperName())
|
||||
|
|
@ -127,7 +127,7 @@ class ApacheHttpclientV3Test {
|
|||
SECRET_KEY + "=" + secretKey;
|
||||
|
||||
String message = buildAuth + "\n" + responseBody + "\n";
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getResult());
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getSignature());
|
||||
|
||||
client.when(request()
|
||||
.withMethod(HttpMethod.POST.getUpperName())
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@ public class TestPrivacyEncryptor extends AbstractPrivacyEncryptor {
|
|||
* @param publicKey 加密使用的公钥
|
||||
*/
|
||||
public TestPrivacyEncryptor(PublicKey publicKey) {
|
||||
super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, null);
|
||||
super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, null, "");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,6 @@ public class TestSigner extends AbstractSigner {
|
|||
* @param privateKey API私钥
|
||||
*/
|
||||
public TestSigner(PrivateKey privateKey) {
|
||||
super("SHA256withRSA", "SHA256withRSA", privateKey, null);
|
||||
super("SHA256withRSA", "SHA256withRSA", privateKey, null, "");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@ public final class RsaPrivacyEncryptor extends AbstractPrivacyEncryptor {
|
|||
* @param publicKey 加密使用的公钥
|
||||
*/
|
||||
public RsaPrivacyEncryptor(PublicKey publicKey) {
|
||||
super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, null);
|
||||
super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, null, "");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.czcb.scfs.api.core.Constants.HEX;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
|
|
@ -40,6 +41,11 @@ public class RsaProfile extends AbstractProfile {
|
|||
return privateKey(PemFile.loadPrivateKeyFromAbsolutePath(privateKeyPath));
|
||||
}
|
||||
|
||||
public Builder addCertificates(List<X509Certificate> certificate) {
|
||||
certificates.addAll(certificate);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addCertificate(X509Certificate certificate) {
|
||||
certificates.add(certificate);
|
||||
return this;
|
||||
|
|
@ -64,7 +70,10 @@ public class RsaProfile extends AbstractProfile {
|
|||
|
||||
CertificateProvider certificateProvider = new LocalCertificateProvider(certificates);
|
||||
this.privacy = new RsaPrivacy(privateKey, certificateProvider);
|
||||
this.signature = new DefaultSignature(certificateProvider, new RsaSigner(privateKey), new RsaVerifier(certificateProvider));
|
||||
X509Certificate certificate = certificateProvider.getAvailableCertificate();
|
||||
this.signature = new DefaultSignature(certificateProvider,
|
||||
new RsaSigner(privateKey, certificate.getSerialNumber().toString(HEX)),
|
||||
new RsaVerifier(certificateProvider));
|
||||
|
||||
httpProfile(httpProfile);
|
||||
if (Objects.isNull(httpProfile)) {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public class RsaSigner extends AbstractSigner {
|
|||
/**
|
||||
* @param privateKey API私钥
|
||||
*/
|
||||
protected RsaSigner(PrivateKey privateKey) {
|
||||
super("SHA256withRSA", "SHA256withRSA", privateKey, null);
|
||||
protected RsaSigner(PrivateKey privateKey, String certificateSerialNumber) {
|
||||
super("SHA256withRSA", "SHA256withRSA", privateKey, null, certificateSerialNumber);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class RsaProfileTest {
|
|||
Assertions.assertNotNull(profile);
|
||||
|
||||
String message = "1234567";
|
||||
String signResult = profile.getSignature().getSigner().sign(message).getResult();
|
||||
String signResult = profile.getSignature().getSigner().sign(message).getSignature();
|
||||
Assertions.assertTrue(profile.getSignature().getVerifier().verify(null, message, signResult));
|
||||
|
||||
Assertions.assertEquals("0000", profile.getChannel().getChannelNo());
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ public class MockResponse {
|
|||
SECRET_KEY + "=" + secretKey;
|
||||
|
||||
String message = buildAuth + "\n" + responseBody + "\n";
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getResult());
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getSignature());
|
||||
return mock;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@ public class TestPrivacyEncryptor extends AbstractPrivacyEncryptor {
|
|||
* @param publicKey 加密使用的公钥
|
||||
*/
|
||||
protected TestPrivacyEncryptor(PublicKey publicKey) {
|
||||
super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, null);
|
||||
super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, null, "");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,6 @@ public class TestSigner extends AbstractSigner {
|
|||
* @param privateKey API私钥
|
||||
*/
|
||||
public TestSigner(PrivateKey privateKey) {
|
||||
super("SHA256withRSA", "SHA256withRSA", privateKey, null);
|
||||
super("SHA256withRSA", "SHA256withRSA", privateKey, null, "");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public final class Sm2PrivacyEncryptor extends AbstractPrivacyEncryptor {
|
|||
/**
|
||||
* @param publicKey 请求的敏感信息加密时使用的国密公钥
|
||||
*/
|
||||
public Sm2PrivacyEncryptor(PublicKey publicKey) {
|
||||
super("SM2", publicKey, SmProvider.getProvider());
|
||||
public Sm2PrivacyEncryptor(PublicKey publicKey, String certificateSerial) {
|
||||
super("SM2", publicKey, SmProvider.getProvider(), certificateSerial);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public class Sm2Signer extends AbstractSigner {
|
|||
*
|
||||
* @param privateKey API私钥
|
||||
*/
|
||||
public Sm2Signer(PrivateKey privateKey) {
|
||||
super("SM3withSM2", "SM2", privateKey, SmProvider.getProvider());
|
||||
public Sm2Signer(PrivateKey privateKey, String certificateSerialNumber) {
|
||||
super("SM3withSM2", "SM2", privateKey, SmProvider.getProvider(), certificateSerialNumber);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.czcb.scfs.api.sm;
|
||||
|
||||
import com.czcb.scfs.api.core.cipher.*;
|
||||
import com.czcb.scfs.api.core.util.Strings;
|
||||
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
|
@ -20,10 +21,13 @@ public class SmPrivacy implements Privacy {
|
|||
|
||||
public SmPrivacy(PrivateKey privateKey, CertificateProvider certificateProvider) {
|
||||
this.privacyDecryptor = new Sm2PrivacyDecryptor(privateKey);
|
||||
|
||||
X509Certificate certificate = certificateProvider.getAvailableCertificate();
|
||||
this.privacyEncryptor = new Sm2PrivacyEncryptor(certificate.getPublicKey());
|
||||
this.secretCipher = new Sm4SecretCipher();
|
||||
|
||||
// 获取有效的证书,多个取最长过期时间
|
||||
X509Certificate certificate = certificateProvider.getAvailableCertificate();
|
||||
|
||||
String serialNumber = Strings.toHexUpper(certificate.getSerialNumber());
|
||||
this.privacyEncryptor = new Sm2PrivacyEncryptor(certificate.getPublicKey(), serialNumber);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ public final class SmProfile extends AbstractProfile {
|
|||
}
|
||||
|
||||
private PrivateKey privateKey;
|
||||
/**
|
||||
* 证书序列号
|
||||
*/
|
||||
private String certificateSerial;
|
||||
private final List<X509Certificate> certificates = new ArrayList<>();
|
||||
private Privacy privacy;
|
||||
private Signature signature;
|
||||
|
|
@ -47,6 +51,17 @@ public final class SmProfile extends AbstractProfile {
|
|||
return privateKey(PemFile.loadPrivateKeyFromAbsolutePath(privateKeyPath, "EC", KonaProvider.NAME));
|
||||
}
|
||||
|
||||
public Builder certificateSerial(String certificateSerial) {
|
||||
Objects.requireNonNull(certificateSerial);
|
||||
this.certificateSerial = certificateSerial.toUpperCase();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addCertificates(List<X509Certificate> certificate) {
|
||||
certificates.addAll(certificate);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addCertificate(X509Certificate certificate) {
|
||||
certificates.add(certificate);
|
||||
return this;
|
||||
|
|
@ -74,7 +89,9 @@ public final class SmProfile extends AbstractProfile {
|
|||
// 加密器
|
||||
this.privacy = new SmPrivacy(privateKey, certificateProvider);
|
||||
// 签名器
|
||||
this.signature = new DefaultSignature(certificateProvider, new Sm2Signer(privateKey), new Sm2Verifier(certificateProvider));
|
||||
this.signature = new DefaultSignature(certificateProvider,
|
||||
new Sm2Signer(privateKey, certificateSerial),
|
||||
new Sm2Verifier(certificateProvider));
|
||||
|
||||
httpProfile(httpProfile);
|
||||
if (Objects.isNull(httpProfile)) {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class SmProfileTest {
|
|||
Assertions.assertNotNull(profile);
|
||||
|
||||
String message = "1234567";
|
||||
String signResult = profile.getSignature().getSigner().sign(message).getResult();
|
||||
String signResult = profile.getSignature().getSigner().sign(message).getSignature();
|
||||
Assertions.assertTrue(profile.getSignature().getVerifier().verify(null, message, signResult));
|
||||
|
||||
Assertions.assertEquals("0000", profile.getChannel().getChannelNo());
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ import javax.annotation.Resource;
|
|||
import java.io.InputStream;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
|
|
@ -27,13 +29,16 @@ public class RsaConfiguration extends AbstractAutoConfiguration {
|
|||
return properties;
|
||||
}
|
||||
|
||||
private X509Certificate getCertificate() {
|
||||
private List<X509Certificate> getCertificates() {
|
||||
if (Objects.equals(getProperties().getCipher().getStoreType(), StoreType.FILE)) {
|
||||
return PemFile.loadX509FromAbsolutePath(getProperties().getCipher().getCertificate());
|
||||
return getProperties().getCipher().getCertificate().stream()
|
||||
.map(PemFile::loadX509FromAbsolutePath)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(getProperties().getCipher().getCertificate());
|
||||
return PemFile.loadX509FromStream(inputStream);
|
||||
return getProperties().getCipher().getCertificate().stream()
|
||||
.map(cert -> PemFile.loadX509FromStream(getClass().getClassLoader().getResourceAsStream(cert)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private PrivateKey getPrivateKey() {
|
||||
|
|
@ -50,7 +55,7 @@ public class RsaConfiguration extends AbstractAutoConfiguration {
|
|||
.channel(getChannel())
|
||||
.httpProfile(getHttpProfile())
|
||||
.privateKey(getPrivateKey())
|
||||
.addCertificate(getCertificate())
|
||||
.addCertificates(getCertificates())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.czcb.scfs.api.core.cipher.StoreType;
|
|||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
|
@ -116,13 +117,13 @@ public class ScfsApiGatewayProperties {
|
|||
|
||||
private String channelPrivateKey;
|
||||
/**
|
||||
* 渠道端证书文件地址
|
||||
* 渠道端证书序列号
|
||||
*/
|
||||
private String channelCertificate;
|
||||
private String channelCertificateSerial;
|
||||
/**
|
||||
* 银行侧证书地址
|
||||
*/
|
||||
private String certificate;
|
||||
private List<String> certificate;
|
||||
|
||||
public StoreType getStoreType() {
|
||||
return storeType;
|
||||
|
|
@ -140,19 +141,19 @@ public class ScfsApiGatewayProperties {
|
|||
this.channelPrivateKey = channelPrivateKey;
|
||||
}
|
||||
|
||||
public String getChannelCertificate() {
|
||||
return channelCertificate;
|
||||
public String getChannelCertificateSerial() {
|
||||
return channelCertificateSerial;
|
||||
}
|
||||
|
||||
public void setChannelCertificate(String channelCertificate) {
|
||||
this.channelCertificate = channelCertificate;
|
||||
public void setChannelCertificateSerial(String channelCertificateSerial) {
|
||||
this.channelCertificateSerial = channelCertificateSerial;
|
||||
}
|
||||
|
||||
public String getCertificate() {
|
||||
public List<String> getCertificate() {
|
||||
return certificate;
|
||||
}
|
||||
|
||||
public void setCertificate(String certificate) {
|
||||
public void setCertificate(List<String> certificate) {
|
||||
this.certificate = certificate;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ import javax.annotation.Resource;
|
|||
import java.io.InputStream;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
|
|
@ -29,13 +31,16 @@ public class SmConfiguration extends AbstractAutoConfiguration {
|
|||
return properties;
|
||||
}
|
||||
|
||||
private X509Certificate getCertificate() {
|
||||
private List<X509Certificate> getCertificates() {
|
||||
if (Objects.equals(getProperties().getCipher().getStoreType(), StoreType.FILE)) {
|
||||
return PemFile.loadX509FromAbsolutePath(getProperties().getCipher().getCertificate(), KonaProvider.NAME);
|
||||
return getProperties().getCipher().getCertificate().stream()
|
||||
.map(cert -> PemFile.loadX509FromAbsolutePath(cert, KonaProvider.NAME))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(getProperties().getCipher().getCertificate());
|
||||
return PemFile.loadX509FromStream(inputStream, KonaProvider.NAME);
|
||||
return getProperties().getCipher().getCertificate().stream()
|
||||
.map(cert -> PemFile.loadX509FromStream(getClass().getClassLoader().getResourceAsStream(cert), KonaProvider.NAME))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private PrivateKey getPrivateKey() {
|
||||
|
|
@ -54,7 +59,8 @@ public class SmConfiguration extends AbstractAutoConfiguration {
|
|||
.channel(getChannel())
|
||||
.httpProfile(getHttpProfile())
|
||||
.privateKey(getPrivateKey())
|
||||
.addCertificate(getCertificate())
|
||||
.certificateSerial(properties.getCipher().getChannelCertificateSerial())
|
||||
.addCertificates(getCertificates())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.czcb.scfs.spring.boot.starter;
|
||||
|
||||
import com.czcb.scfs.api.core.cipher.StoreType;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
|
@ -84,8 +85,8 @@ class ScfsApiGatewayPropertiesTest {
|
|||
ScfsApiGatewayProperties.Cipher cipher = new ScfsApiGatewayProperties.Cipher();
|
||||
cipher.setStoreType(StoreType.RESOURCES);
|
||||
cipher.setChannelPrivateKey("/home/key.pem");
|
||||
cipher.setChannelCertificate("/home/c1.pem");
|
||||
cipher.setCertificate("/home/c2.pem");
|
||||
cipher.setChannelCertificateSerial("/home/c1.pem");
|
||||
cipher.setCertificate(Lists.newArrayList("/home/c2.pem"));
|
||||
|
||||
ScfsApiGatewayProperties properties = new ScfsApiGatewayProperties();
|
||||
properties.setCipher(cipher);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.czcb.scfs.spring.boot.starter;
|
||||
|
||||
import com.czcb.scfs.api.core.cipher.StoreType;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
|
@ -52,8 +53,8 @@ class SmConfigurationTest {
|
|||
ScfsApiGatewayProperties.Cipher cipher = new ScfsApiGatewayProperties.Cipher();
|
||||
cipher.setStoreType(StoreType.RESOURCES);
|
||||
cipher.setChannelPrivateKey("/home/key.pem");
|
||||
cipher.setChannelCertificate("/home/c1.pem");
|
||||
cipher.setCertificate("/home/c2.pem");
|
||||
cipher.setChannelCertificateSerial("/home/c1.pem");
|
||||
cipher.setCertificate(Lists.list("/home/c2.pem"));
|
||||
properties.setCipher(cipher);
|
||||
|
||||
properties.setOnline(true);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
scfs.api-gateway.online=false
|
||||
scfs.api-gateway.host=http://127.0.0.1:8088/api-gateway
|
||||
scfs.api-gateway.channel.app-no=10001
|
||||
scfs.api-gateway.channel.channel-no=1000
|
||||
scfs.api-gateway.channel.channel-no=0000
|
||||
scfs.api-gateway.channel.app-no=000000
|
||||
scfs.api-gateway.cipher.store-type=resources
|
||||
#scfs.api-gateway.cipher.channel-private-key=rsa_channel_private_key.pem
|
||||
#scfs.api-gateway.cipher.certificate=rsa_channel_certificate.pem
|
||||
scfs.api-gateway.cipher.channel-private-key=merchant_private_key.pem
|
||||
scfs.api-gateway.cipher.certificate=merchant_certificate.pem
|
||||
scfs.api-gateway.cipher.channel-private-key=sm2_private_key.pem
|
||||
scfs.api-gateway.cipher.channel-certificate-serial=12312312879h89u8hhh89h989
|
||||
scfs.api-gateway.cipher.certificate=scfs_sm2_certificate.pem
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICKDCCAc+gAwIBAgIhAMPbc74uYS3FysLkYMHB5P+q7DCzriTkomU9a3S9QAL9MAoGCCqBHM9V
|
||||
AYN1MIGNMQswCQYDVQQGEwJDTjESMBAGA1UECAwJ5rWZ5rGf55yBMRIwEAYDVQQHDAnmna3lt57l
|
||||
uIIxITAfBgNVBAoMGOa1meaxn+eooOW3nuWVhuS4mumTtuihjDEYMBYGA1UECwwP5pWw5a2X6YeR
|
||||
6J6N6YOoMRkwFwYDVQQDDBBzY2ZzLmN6Y2IuY29tLmNuMB4XDTI0MDIyMTA1NDU0MFoXDTI5MDIy
|
||||
MTA1NDU0MFowgY0xCzAJBgNVBAYTAkNOMRIwEAYDVQQIDAnmtZnmsZ/nnIExEjAQBgNVBAcMCead
|
||||
reW3nuW4gjEhMB8GA1UECgwY5rWZ5rGf56ig5bee5ZWG5Lia6ZO26KGMMRgwFgYDVQQLDA/mlbDl
|
||||
rZfph5Hono3pg6gxGTAXBgNVBAMMEHNjZnMuY3pjYi5jb20uY24wWTATBgcqhkjOPQIBBggqgRzP
|
||||
VQGCLQNCAAS3xG2kVL1N2p71VUsFO5WyD2QCzq5SFarPpKlYpEXCx57QeEUypZFmvzTDNpWv5y11
|
||||
e798SvOBSmZTFrF6CStIMAoGCCqBHM9VAYN1A0cAMEQCIHVbD5xUf/6OORWvelFm9wSHuTQ5NRjC
|
||||
iKP4iOpCTS+oAiB4VVZ0XOdVr3ENWvzI2c1ZVvkLXy4T66CQc/Pg57P0/Q==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgplcULkGrRiFDra/9MywSc4Ornu/k
|
||||
jdlSSXCqoHPPM0WgCgYIKoEcz1UBgi2hRANCAAS3xG2kVL1N2p71VUsFO5WyD2QCzq5SFarPpKlY
|
||||
pEXCx57QeEUypZFmvzTDNpWv5y11e798SvOBSmZTFrF6CStI
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIICGTCCAcCgAwIBAgIhAPtOPc4Cl0OO05B3H0ZXa5L9fmt/HpvRKn2H6CG1mUjlMAoGCCqBHM9V
|
||||
AYN1MIGNMQswCQYDVQQGEwJDTjESMBAGA1UECAwJ5rWZ5rGf55yBMRIwEAYDVQQHDAnmna3lt57l
|
||||
uIIxITAfBgNVBAoMGOa1meaxn+eooOW3nuWVhuS4mumTtuihjDEYMBYGA1UECwwP5pWw5a2X6YeR
|
||||
6J6N6YOoMRkwFwYDVQQDDBBzY2ZzLmN6Y2IuY29tLmNuMB4XDTI0MDMyNjA4NDU1MFoXDTI5MDMy
|
||||
NjA4NDU1MFowfzELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCea1meaxn+ecgTESMBAGA1UEBwwJ5p2t
|
||||
5bee5biCMSEwHwYDVQQKDBjmtZnmsZ/nqKDlt57llYbkuJrpk7booYwxJTAjBgNVBAsMHOaVsOWt
|
||||
l+mHkeiejemDqC3mtYvor5Xor4HkuaYwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAAT0KcBDXLn6
|
||||
Zv5vsEtuDzZclr30phN++uOVaQoFcDhhbeZlqRSIqRdg6YstCHUenN7NL2S1b1JlsWeIUxGCndZU
|
||||
MAoGCCqBHM9VAYN1A0cAMEQCIGp00kvdZqtobJ9X7YHAKBtGZXnXBKeuhdM+ZIhYelwBAiB1Dv0s
|
||||
0ahzWO+jJ/DVN8zM1b4noePZArFed8qHXsvt+Q==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgR6jTgU+vLuT00j3QM7b/fPJ9iUGR
|
||||
zZeVwr90JeVhChygCgYIKoEcz1UBgi2hRANCAAT0KcBDXLn6Zv5vsEtuDzZclr30phN++uOVaQoF
|
||||
cDhhbeZlqRSIqRdg6YstCHUenN7NL2S1b1JlsWeIUxGCndZU
|
||||
-----END PRIVATE KEY-----
|
||||
|
|
@ -31,8 +31,8 @@ class ApiGatewayTest {
|
|||
@Test
|
||||
void testQuery() {
|
||||
QueryBalanceRequest queryBalanceRequest = new QueryBalanceRequest();
|
||||
queryBalanceRequest.setChannelNo("1012");
|
||||
queryBalanceRequest.setAppNo("");
|
||||
queryBalanceRequest.setChannelNo("0000");
|
||||
queryBalanceRequest.setAppNo("000000");
|
||||
queryBalanceRequest.setSerialNo(UUID.randomUUID().toString().replace("-", ""));
|
||||
queryBalanceRequest.setAccountNo("1012230221000010");
|
||||
queryBalanceRequest.setRelationAcct("1");
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public class MockResponse {
|
|||
SECRET_KEY + "=" + secretKey;
|
||||
|
||||
String message = buildAuth + "\n" + responseBody + "\n";
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getResult());
|
||||
mock.withHeader(SIGNATURE, apiClient.getProfile().getSignature().getSigner().sign(message).getSignature());
|
||||
return mock;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue