请求携带 证书序列号

main
13009 2024-04-01 15:32:25 +08:00
parent b09bec5c2b
commit 6063c84f32
49 changed files with 219 additions and 121 deletions

View File

@ -17,6 +17,11 @@ public final class Constants {
public static final String APP_NO = "X-SCFS-App-No"; public static final String APP_NO = "X-SCFS-App-No";
public static final String SIGNATURE = "X-SCFS-Signature"; public static final String SIGNATURE = "X-SCFS-Signature";
public static final String API_VERSION = "X-SCFS-Api-Version"; 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 自定义字段 // http 自定义字段
public static final String TIMESTAMP = "X-SCFS-Timestamp"; public static final String TIMESTAMP = "X-SCFS-Timestamp";
public static final String NONCE = "X-SCFS-Nonce"; public static final String NONCE = "X-SCFS-Nonce";

View File

@ -23,6 +23,7 @@ public abstract class AbstractPrivacyEncryptor implements PrivacyEncryptor {
protected final String transformation; protected final String transformation;
protected final PublicKey publicKey; protected final PublicKey publicKey;
protected final Provider provider; protected final Provider provider;
private final String certificateSerial;
/** /**
* *
@ -31,10 +32,11 @@ public abstract class AbstractPrivacyEncryptor implements PrivacyEncryptor {
* @param publicKey 使 * @param publicKey 使
* @param provider * @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.transformation = requireNonNull(transformation);
this.publicKey = requireNonNull(publicKey); this.publicKey = requireNonNull(publicKey);
this.provider = provider; this.provider = provider;
this.certificateSerial = certificateSerial;
} }
/** /**
@ -76,4 +78,9 @@ public abstract class AbstractPrivacyEncryptor implements PrivacyEncryptor {
public PublicKey getPublicKey() { public PublicKey getPublicKey() {
return publicKey; return publicKey;
} }
@Override
public String getCertificateSerial() {
return certificateSerial;
}
} }

View File

@ -19,6 +19,7 @@ public abstract class AbstractSigner implements Signer {
protected final String algorithmName; protected final String algorithmName;
protected final PrivateKey privateKey; protected final PrivateKey privateKey;
protected final Provider provider; protected final Provider provider;
private final String certificateSerial;
/** /**
* AbstractSigner * AbstractSigner
@ -27,11 +28,12 @@ public abstract class AbstractSigner implements Signer {
* @param algorithmName SignatureSHA256withRSA * @param algorithmName SignatureSHA256withRSA
* @param privateKey API * @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.algorithm = requireNonNull(algorithm);
this.algorithmName = requireNonNull(algorithmName); this.algorithmName = requireNonNull(algorithmName);
this.privateKey = requireNonNull(privateKey); this.privateKey = requireNonNull(privateKey);
this.provider = provider; this.provider = provider;
this.certificateSerial = requireNonNull(certificateSerial);
} }
private java.security.Signature getSignature() { private java.security.Signature getSignature() {
@ -51,7 +53,7 @@ public abstract class AbstractSigner implements Signer {
java.security.Signature signature = getSignature(); java.security.Signature signature = getSignature();
signature.initSign(privateKey); signature.initSign(privateKey);
signature.update(Strings.toBytes(message)); signature.update(Strings.toBytes(message));
return new SignatureResult(Base64.encodeStr(signature.sign())); return new SignatureResult(getCertificateSerial(), Base64.encodeStr(signature.sign()));
} catch (InvalidKeyException e) { } catch (InvalidKeyException e) {
throw new IllegalArgumentException(algorithm + " signature uses an illegal privateKey.", e); throw new IllegalArgumentException(algorithm + " signature uses an illegal privateKey.", e);
} catch (SignatureException e) { } catch (SignatureException e) {
@ -59,6 +61,11 @@ public abstract class AbstractSigner implements Signer {
} }
} }
@Override
public String getCertificateSerial() {
return certificateSerial;
}
@Override @Override
public String getAlgorithm() { public String getAlgorithm() {
return algorithm; return algorithm;

View File

@ -58,9 +58,9 @@ public abstract class AbstractVerifier implements Verifier {
@Override @Override
public boolean verify(String serialNumber, String message, String signature) { public boolean verify(String serialNumber, String message, String signature) {
X509Certificate certificate = certificateProvider.getAvailableCertificate(); X509Certificate certificate = certificateProvider.getCertificate(serialNumber);
if (certificate == null) { if (certificate == null) {
logger.error("校验证书不存在"); logger.error("校验证书不存在, 证书序列号: {}", serialNumber);
return false; return false;
} }
return verify(certificate, message, signature); return verify(certificate, message, signature);

View File

@ -1,6 +1,5 @@
package com.czcb.scfs.api.core.cipher; package com.czcb.scfs.api.core.cipher;
import java.math.BigInteger;
import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
@ -14,13 +13,13 @@ import java.util.Map;
*/ */
public class CertificateValidity { public class CertificateValidity {
public X509Certificate getLongestCertificate(Map<BigInteger, X509Certificate> certificates) { public X509Certificate getLongestCertificate(Map<String, X509Certificate> certificates) {
if (certificates == null || certificates.isEmpty()) { if (certificates == null || certificates.isEmpty()) {
return null; return null;
} }
X509Certificate longest = 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())) { if (longest == null || item.getValue().getNotAfter().after(longest.getNotAfter())) {
longest = item.getValue(); longest = item.getValue();
} }

View File

@ -26,17 +26,18 @@ public class DefaultCredential implements Credential {
@Override @Override
public String buildRequestAuthorization(HttpRequest request, Channel channel) { 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(NONCE, request.getId());
request.getHttpHeaders().addHeader(TIMESTAMP, DateTimes.ofTimestamp()); 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 // 签名头 X-SCFS-Nonce=xx,X-SCFS-Timestamp=xxx,X-SCFS-Secret-Key=xx
String signatureHeader = getSignatureHeader(request.getHttpHeaders()); String signatureHeader = getSignatureHeader(request.getHttpHeaders());
// 请求方法GET/POST需要大写 // 请求方法GET/POST需要大写
@ -48,14 +49,16 @@ public class DefaultCredential implements Credential {
// 构建待签名串 // 构建待签名串
String message = buildRequestMessage(signatureHeader, method, url, body); String message = buildRequestMessage(signatureHeader, method, url, body);
// 私钥加签 // 私钥加签
return signer.sign(message).getResult(); return signer.sign(message);
} }
private String getSignatureHeader(HttpHeaders httpHeaders) { private String getSignatureHeader(HttpHeaders httpHeaders) {
Map<String, String> headers = httpHeaders.getHeaders(); Map<String, String> headers = httpHeaders.getHeaders();
return NONCE + "=" + headers.get(NONCE) + "," + return NONCE + "=" + Strings.fmtEmpty(headers.get(NONCE)) + "," +
TIMESTAMP + "=" + headers.get(TIMESTAMP) + "," + TIMESTAMP + "=" + Strings.fmtEmpty(headers.get(TIMESTAMP)) + "," +
SECRET_KEY + "=" + headers.get(SECRET_KEY); 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) { private String getSignatureBody(HttpRequest request) {
@ -72,11 +75,11 @@ public class DefaultCredential implements Credential {
requestBody + "\n"; requestBody + "\n";
} }
private String authText(Channel channel, String signature) { private String authorizationMessage(Channel channel, SignatureResult result) {
// 认证串 // 认证串
return CHANNEL_NO + "=" + channel.getChannelNo() + "," + return CHANNEL_NO + "=" + channel.getChannelNo() + "," +
APP_NO + "=" + channel.getAppNo() + "," + APP_NO + "=" + channel.getAppNo() + "," +
SIGNATURE + "=" + signature; SIGNATURE + "=" + result.getSignature();
} }
@Override @Override

View File

@ -66,7 +66,6 @@ public final class DefaultValidator implements Validator {
// 校验时间戳 // 校验时间戳
validateTimestamp(request, response); validateTimestamp(request, response);
// 请求头包含 SecretKey 进行验签
if (!headerContainsSecretKey(response)) { if (!headerContainsSecretKey(response)) {
return; return;
} }
@ -80,7 +79,9 @@ public final class DefaultValidator implements Validator {
response.getHttpHeaders().getHeader(REQUEST_ID))); 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); httpLogger.logResponseError(request, response);
throw new ValidationException(String.format("响应校验失败, 签名校验未通过, Request-Id=%s", throw new ValidationException(String.format("响应校验失败, 签名校验未通过, Request-Id=%s",
response.getHttpHeaders().getHeader(REQUEST_ID))); response.getHttpHeaders().getHeader(REQUEST_ID)));
@ -91,6 +92,8 @@ public final class DefaultValidator implements Validator {
} }
private boolean headerContainsSecretKey(OriginalResponse response) { 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));
} }
} }

View File

@ -1,15 +1,14 @@
package com.czcb.scfs.api.core.cipher; package com.czcb.scfs.api.core.cipher;
import com.czcb.scfs.api.core.util.DateTimes;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap; 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 * ConcurrentHashMap
@ -19,7 +18,7 @@ import static com.czcb.scfs.api.core.Constants.HEX;
public final class LocalCertificateProvider implements CertificateProvider { public final class LocalCertificateProvider implements CertificateProvider {
private final Logger logger = LoggerFactory.getLogger(getClass()); 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 final CertificateValidity validity = new CertificateValidity();
private X509Certificate availableCertificate; private X509Certificate availableCertificate;
@ -40,22 +39,16 @@ public final class LocalCertificateProvider implements CertificateProvider {
*/ */
@Override @Override
public X509Certificate getCertificate(String serialNumber) { public X509Certificate getCertificate(String serialNumber) {
BigInteger key = new BigInteger(serialNumber, HEX); return certificates.get(serialNumber);
return certificates.get(key);
} }
public void addX509Certificate(X509Certificate certificate) { public void addX509Certificate(X509Certificate certificate) {
if (!validity.withinValidity(certificate)) { if (!validity.withinValidity(certificate)) {
logger.error("证书已失效, 序列号:{}, 有效范围:[{}]", certificate.getSerialNumber(), timeRange(certificate)); logger.error("证书已失效, 序列号:{}, 有效范围:[{}]", toHexUpper(certificate.getSerialNumber()), timeRange(certificate));
return; return;
} }
certificates.put(certificate.getSerialNumber(), certificate); certificates.put(toHexUpper(certificate.getSerialNumber()), certificate);
}
private String timeRange(X509Certificate certificate) {
return String.format("%s,%s", DateTimes.ofPatternDate(certificate.getNotBefore()),
DateTimes.ofPatternDate(certificate.getNotAfter()));
} }
/** /**

View File

@ -23,4 +23,6 @@ public interface PrivacyEncryptor {
* @return PublicKey * @return PublicKey
*/ */
PublicKey getPublicKey(); PublicKey getPublicKey();
String getCertificateSerial();
} }

View File

@ -10,18 +10,27 @@ import static java.util.Objects.requireNonNull;
* @since 2.0.0 * @since 2.0.0
*/ */
public class SignatureResult { public class SignatureResult {
private final String certificateSerial;
private final String signature; private final String signature;
public SignatureResult(String signature) { public SignatureResult(String certificateSerial, String signature) {
this.certificateSerial = certificateSerial;
this.signature = requireNonNull(signature); this.signature = requireNonNull(signature);
} }
/**
* @return
*/
public String getCertificateSerial() {
return certificateSerial;
}
/** /**
* *
* *
* @return * @return
*/ */
public String getResult() { public String getSignature() {
return signature; return signature;
} }

View File

@ -14,6 +14,8 @@ public interface Signer {
*/ */
SignatureResult sign(String message); SignatureResult sign(String message);
String getCertificateSerial();
/** /**
* *
* *

View File

@ -15,4 +15,4 @@ public interface Verifier {
* @return * @return
*/ */
boolean verify(String serialNumber, String message, String signature); boolean verify(String serialNumber, String message, String signature);
} }

View File

@ -139,9 +139,12 @@ public abstract class AbstractApiClient implements ApiClient {
// 生成密钥 // 生成密钥
byte[] secretKey = cipher.getSecretKey(); 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(SECRET_KEY, encryptSecretKey);
// 加密证书序列号
httpRequest.getHttpHeaders().addHeader(BANK_CERTIFICATE_SERIAL, encryptor.getCertificateSerial());
// 原始body // 原始body
byte[] originalBody = httpRequest.getRequestBody().getBody(); byte[] originalBody = httpRequest.getRequestBody().getBody();

View File

@ -2,12 +2,16 @@ package com.czcb.scfs.api.core.util;
import com.czcb.scfs.api.core.exception.EncodingException; import com.czcb.scfs.api.core.exception.EncodingException;
import java.math.BigInteger;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Objects; import java.util.Objects;
import java.util.Random; import java.util.Random;
import static com.czcb.scfs.api.core.Constants.HEX;
/** /**
* @author wangwei * @author wangwei
* @since 2.0.0 * @since 2.0.0
@ -93,4 +97,21 @@ public class Strings {
throw new EncodingException(e); 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()));
}
} }

View File

@ -43,7 +43,7 @@ class AbstractPrivacyEncryptorTest {
private static class TestPrivacyEncryptorv2 extends AbstractPrivacyEncryptor { private static class TestPrivacyEncryptorv2 extends AbstractPrivacyEncryptor {
public TestPrivacyEncryptorv2(PublicKey publicKey, Provider provider) { public TestPrivacyEncryptorv2(PublicKey publicKey, Provider provider) {
super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, provider); super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, provider, "");
} }
} }
} }

View File

@ -17,7 +17,7 @@ class AbstractSignerTest {
void sign() { void sign() {
TestSigner signer = new TestSigner(KeyText.loadTestPrivateKeyRSA(), null); TestSigner signer = new TestSigner(KeyText.loadTestPrivateKeyRSA(), null);
String message = "1234567890"; String message = "1234567890";
String sg = signer.sign(message).getResult(); String sg = signer.sign(message).getSignature();
Assertions.assertNotNull(sg); Assertions.assertNotNull(sg);
Assertions.assertEquals("SHA256withRSA", signer.getAlgorithm()); Assertions.assertEquals("SHA256withRSA", signer.getAlgorithm());
@ -41,12 +41,12 @@ class AbstractSignerTest {
* @param privateKey API * @param privateKey API
*/ */
public TestSigner(PrivateKey privateKey, Provider provider) { public TestSigner(PrivateKey privateKey, Provider provider) {
super("SHA256withRSA", "SHA256withRSA", privateKey, provider); super("SHA256withRSA", "SHA256withRSA", privateKey, provider, "");
} }
public TestSigner(PrivateKey privateKey) { public TestSigner(PrivateKey privateKey) {
// 错误的签名算法 // 错误的签名算法
super("SHA256withRSA1", "SHA256withRSA1", privateKey, null); super("SHA256withRSA1", "SHA256withRSA1", privateKey, null, "");
} }
} }
} }

View File

@ -5,7 +5,6 @@ import com.czcb.scfs.api.core.util.PemFile;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.math.BigInteger;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.HashMap; import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -64,9 +63,9 @@ class CertificateValidityTest {
Assertions.assertNull(validity.getLongestCertificate(null)); Assertions.assertNull(validity.getLongestCertificate(null));
Assertions.assertNull(validity.getLongestCertificate(new HashMap<>())); Assertions.assertNull(validity.getLongestCertificate(new HashMap<>()));
ConcurrentHashMap<BigInteger, X509Certificate> certificates = new ConcurrentHashMap<>(); ConcurrentHashMap<String, X509Certificate> certificates = new ConcurrentHashMap<>();
X509Certificate certificate = KeyText.loadTestRSA(); X509Certificate certificate = KeyText.loadTestRSA();
certificates.put(certificate.getSerialNumber(), certificate); certificates.put(certificate.getSerialNumber().toString(), certificate);
Assertions.assertNotNull(validity.getLongestCertificate(certificates)); Assertions.assertNotNull(validity.getLongestCertificate(certificates));
} }

View File

@ -7,13 +7,13 @@ class SignatureResultTest {
@Test @Test
void getResult() { void getResult() {
SignatureResult result = new SignatureResult("123456"); SignatureResult result = new SignatureResult("", "123456");
Assertions.assertEquals("123456", result.getResult()); Assertions.assertEquals("123456", result.getSignature());
} }
@Test @Test
void testToString() { void testToString() {
SignatureResult result = new SignatureResult("123456"); SignatureResult result = new SignatureResult("", "123456");
Assertions.assertEquals("{\"signature\":\"123456\"}", result.toString()); Assertions.assertEquals("{\"signature\":\"123456\"}", result.toString());
} }
} }

View File

@ -84,7 +84,7 @@ class ApacheHttpclientProxyTest {
SECRET_KEY + "=" + secretKey; SECRET_KEY + "=" + secretKey;
String message = buildAuth + "\n" + responseBody + "\n"; 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() client.when(request()
.withMethod(HttpMethod.POST.getUpperName()) .withMethod(HttpMethod.POST.getUpperName())

View File

@ -123,7 +123,7 @@ class ApacheHttpclientTest {
SECRET_KEY + "=" + secretKey; SECRET_KEY + "=" + secretKey;
String message = buildAuth + "\n" + responseBody + "\n"; 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() client.when(request()
.withMethod(HttpMethod.POST.getUpperName()) .withMethod(HttpMethod.POST.getUpperName())

View File

@ -84,7 +84,7 @@ class ApacheHttpclientTestProxyTest {
SECRET_KEY + "=" + secretKey; SECRET_KEY + "=" + secretKey;
String message = buildAuth + "\n" + responseBody + "\n"; 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() client.when(request()
.withMethod(HttpMethod.POST.getUpperName()) .withMethod(HttpMethod.POST.getUpperName())

View File

@ -85,7 +85,7 @@ class ApacheHttpclientV2Test {
SECRET_KEY + "=" + secretKey; SECRET_KEY + "=" + secretKey;
String message = buildAuth + "\n" + "\n"; 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() client.when(request()
.withMethod(HttpMethod.POST.getUpperName()) .withMethod(HttpMethod.POST.getUpperName())
@ -129,7 +129,7 @@ class ApacheHttpclientV2Test {
SECRET_KEY + "=" + secretKey; SECRET_KEY + "=" + secretKey;
String message = buildAuth + "\n" + responseBody + "\n"; 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() client.when(request()
.withMethod(HttpMethod.GET.getUpperName()) .withMethod(HttpMethod.GET.getUpperName())

View File

@ -85,7 +85,7 @@ class ApacheHttpclientV3Test {
SECRET_KEY + "=" + secretKey; SECRET_KEY + "=" + secretKey;
String message = buildAuth + "\n" + "\n"; 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() client.when(request()
.withMethod(HttpMethod.POST.getUpperName()) .withMethod(HttpMethod.POST.getUpperName())
@ -127,7 +127,7 @@ class ApacheHttpclientV3Test {
SECRET_KEY + "=" + secretKey; SECRET_KEY + "=" + secretKey;
String message = buildAuth + "\n" + responseBody + "\n"; 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() client.when(request()
.withMethod(HttpMethod.POST.getUpperName()) .withMethod(HttpMethod.POST.getUpperName())

View File

@ -11,6 +11,6 @@ public class TestPrivacyEncryptor extends AbstractPrivacyEncryptor {
* @param publicKey 使 * @param publicKey 使
*/ */
public TestPrivacyEncryptor(PublicKey publicKey) { public TestPrivacyEncryptor(PublicKey publicKey) {
super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, null); super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, null, "");
} }
} }

View File

@ -14,6 +14,6 @@ public class TestSigner extends AbstractSigner {
* @param privateKey API * @param privateKey API
*/ */
public TestSigner(PrivateKey privateKey) { public TestSigner(PrivateKey privateKey) {
super("SHA256withRSA", "SHA256withRSA", privateKey, null); super("SHA256withRSA", "SHA256withRSA", privateKey, null, "");
} }
} }

View File

@ -16,6 +16,6 @@ public final class RsaPrivacyEncryptor extends AbstractPrivacyEncryptor {
* @param publicKey 使 * @param publicKey 使
*/ */
public RsaPrivacyEncryptor(PublicKey publicKey) { public RsaPrivacyEncryptor(PublicKey publicKey) {
super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, null); super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, null, "");
} }
} }

View File

@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import static com.czcb.scfs.api.core.Constants.HEX;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
/** /**
@ -40,6 +41,11 @@ public class RsaProfile extends AbstractProfile {
return privateKey(PemFile.loadPrivateKeyFromAbsolutePath(privateKeyPath)); return privateKey(PemFile.loadPrivateKeyFromAbsolutePath(privateKeyPath));
} }
public Builder addCertificates(List<X509Certificate> certificate) {
certificates.addAll(certificate);
return this;
}
public Builder addCertificate(X509Certificate certificate) { public Builder addCertificate(X509Certificate certificate) {
certificates.add(certificate); certificates.add(certificate);
return this; return this;
@ -64,7 +70,10 @@ public class RsaProfile extends AbstractProfile {
CertificateProvider certificateProvider = new LocalCertificateProvider(certificates); CertificateProvider certificateProvider = new LocalCertificateProvider(certificates);
this.privacy = new RsaPrivacy(privateKey, certificateProvider); 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); httpProfile(httpProfile);
if (Objects.isNull(httpProfile)) { if (Objects.isNull(httpProfile)) {

View File

@ -13,7 +13,7 @@ public class RsaSigner extends AbstractSigner {
/** /**
* @param privateKey API * @param privateKey API
*/ */
protected RsaSigner(PrivateKey privateKey) { protected RsaSigner(PrivateKey privateKey, String certificateSerialNumber) {
super("SHA256withRSA", "SHA256withRSA", privateKey, null); super("SHA256withRSA", "SHA256withRSA", privateKey, null, certificateSerialNumber);
} }
} }

View File

@ -27,7 +27,7 @@ class RsaProfileTest {
Assertions.assertNotNull(profile); Assertions.assertNotNull(profile);
String message = "1234567"; 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.assertTrue(profile.getSignature().getVerifier().verify(null, message, signResult));
Assertions.assertEquals("0000", profile.getChannel().getChannelNo()); Assertions.assertEquals("0000", profile.getChannel().getChannelNo());

View File

@ -80,7 +80,7 @@ public class MockResponse {
SECRET_KEY + "=" + secretKey; SECRET_KEY + "=" + secretKey;
String message = buildAuth + "\n" + responseBody + "\n"; 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; return mock;
} }
} }

View File

@ -11,6 +11,6 @@ public class TestPrivacyEncryptor extends AbstractPrivacyEncryptor {
* @param publicKey 使 * @param publicKey 使
*/ */
protected TestPrivacyEncryptor(PublicKey publicKey) { protected TestPrivacyEncryptor(PublicKey publicKey) {
super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, null); super("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", publicKey, null, "");
} }
} }

View File

@ -14,6 +14,6 @@ public class TestSigner extends AbstractSigner {
* @param privateKey API * @param privateKey API
*/ */
public TestSigner(PrivateKey privateKey) { public TestSigner(PrivateKey privateKey) {
super("SHA256withRSA", "SHA256withRSA", privateKey, null); super("SHA256withRSA", "SHA256withRSA", privateKey, null, "");
} }
} }

View File

@ -13,7 +13,7 @@ public final class Sm2PrivacyEncryptor extends AbstractPrivacyEncryptor {
/** /**
* @param publicKey 使 * @param publicKey 使
*/ */
public Sm2PrivacyEncryptor(PublicKey publicKey) { public Sm2PrivacyEncryptor(PublicKey publicKey, String certificateSerial) {
super("SM2", publicKey, SmProvider.getProvider()); super("SM2", publicKey, SmProvider.getProvider(), certificateSerial);
} }
} }

View File

@ -14,7 +14,7 @@ public class Sm2Signer extends AbstractSigner {
* *
* @param privateKey API * @param privateKey API
*/ */
public Sm2Signer(PrivateKey privateKey) { public Sm2Signer(PrivateKey privateKey, String certificateSerialNumber) {
super("SM3withSM2", "SM2", privateKey, SmProvider.getProvider()); super("SM3withSM2", "SM2", privateKey, SmProvider.getProvider(), certificateSerialNumber);
} }
} }

View File

@ -1,6 +1,7 @@
package com.czcb.scfs.api.sm; package com.czcb.scfs.api.sm;
import com.czcb.scfs.api.core.cipher.*; import com.czcb.scfs.api.core.cipher.*;
import com.czcb.scfs.api.core.util.Strings;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
@ -20,10 +21,13 @@ public class SmPrivacy implements Privacy {
public SmPrivacy(PrivateKey privateKey, CertificateProvider certificateProvider) { public SmPrivacy(PrivateKey privateKey, CertificateProvider certificateProvider) {
this.privacyDecryptor = new Sm2PrivacyDecryptor(privateKey); this.privacyDecryptor = new Sm2PrivacyDecryptor(privateKey);
X509Certificate certificate = certificateProvider.getAvailableCertificate();
this.privacyEncryptor = new Sm2PrivacyEncryptor(certificate.getPublicKey());
this.secretCipher = new Sm4SecretCipher(); this.secretCipher = new Sm4SecretCipher();
// 获取有效的证书,多个取最长过期时间
X509Certificate certificate = certificateProvider.getAvailableCertificate();
String serialNumber = Strings.toHexUpper(certificate.getSerialNumber());
this.privacyEncryptor = new Sm2PrivacyEncryptor(certificate.getPublicKey(), serialNumber);
} }
@Override @Override

View File

@ -32,6 +32,10 @@ public final class SmProfile extends AbstractProfile {
} }
private PrivateKey privateKey; private PrivateKey privateKey;
/**
*
*/
private String certificateSerial;
private final List<X509Certificate> certificates = new ArrayList<>(); private final List<X509Certificate> certificates = new ArrayList<>();
private Privacy privacy; private Privacy privacy;
private Signature signature; private Signature signature;
@ -47,6 +51,17 @@ public final class SmProfile extends AbstractProfile {
return privateKey(PemFile.loadPrivateKeyFromAbsolutePath(privateKeyPath, "EC", KonaProvider.NAME)); 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) { public Builder addCertificate(X509Certificate certificate) {
certificates.add(certificate); certificates.add(certificate);
return this; return this;
@ -74,7 +89,9 @@ public final class SmProfile extends AbstractProfile {
// 加密器 // 加密器
this.privacy = new SmPrivacy(privateKey, certificateProvider); 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); httpProfile(httpProfile);
if (Objects.isNull(httpProfile)) { if (Objects.isNull(httpProfile)) {

View File

@ -28,7 +28,7 @@ class SmProfileTest {
Assertions.assertNotNull(profile); Assertions.assertNotNull(profile);
String message = "1234567"; 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.assertTrue(profile.getSignature().getVerifier().verify(null, message, signResult));
Assertions.assertEquals("0000", profile.getChannel().getChannelNo()); Assertions.assertEquals("0000", profile.getChannel().getChannelNo());

View File

@ -10,7 +10,9 @@ import javax.annotation.Resource;
import java.io.InputStream; import java.io.InputStream;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors;
/** /**
* @since 2.0.0 * @since 2.0.0
@ -27,13 +29,16 @@ public class RsaConfiguration extends AbstractAutoConfiguration {
return properties; return properties;
} }
private X509Certificate getCertificate() { private List<X509Certificate> getCertificates() {
if (Objects.equals(getProperties().getCipher().getStoreType(), StoreType.FILE)) { 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 getProperties().getCipher().getCertificate().stream()
return PemFile.loadX509FromStream(inputStream); .map(cert -> PemFile.loadX509FromStream(getClass().getClassLoader().getResourceAsStream(cert)))
.collect(Collectors.toList());
} }
private PrivateKey getPrivateKey() { private PrivateKey getPrivateKey() {
@ -50,7 +55,7 @@ public class RsaConfiguration extends AbstractAutoConfiguration {
.channel(getChannel()) .channel(getChannel())
.httpProfile(getHttpProfile()) .httpProfile(getHttpProfile())
.privateKey(getPrivateKey()) .privateKey(getPrivateKey())
.addCertificate(getCertificate()) .addCertificates(getCertificates())
.build(); .build();
} }
} }

View File

@ -4,6 +4,7 @@ import com.czcb.scfs.api.core.cipher.StoreType;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -116,13 +117,13 @@ public class ScfsApiGatewayProperties {
private String channelPrivateKey; private String channelPrivateKey;
/** /**
* *
*/ */
private String channelCertificate; private String channelCertificateSerial;
/** /**
* *
*/ */
private String certificate; private List<String> certificate;
public StoreType getStoreType() { public StoreType getStoreType() {
return storeType; return storeType;
@ -140,19 +141,19 @@ public class ScfsApiGatewayProperties {
this.channelPrivateKey = channelPrivateKey; this.channelPrivateKey = channelPrivateKey;
} }
public String getChannelCertificate() { public String getChannelCertificateSerial() {
return channelCertificate; return channelCertificateSerial;
} }
public void setChannelCertificate(String channelCertificate) { public void setChannelCertificateSerial(String channelCertificateSerial) {
this.channelCertificate = channelCertificate; this.channelCertificateSerial = channelCertificateSerial;
} }
public String getCertificate() { public List<String> getCertificate() {
return certificate; return certificate;
} }
public void setCertificate(String certificate) { public void setCertificate(List<String> certificate) {
this.certificate = certificate; this.certificate = certificate;
} }
} }

View File

@ -13,7 +13,9 @@ import javax.annotation.Resource;
import java.io.InputStream; import java.io.InputStream;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors;
/** /**
* @since 2.0.0 * @since 2.0.0
@ -29,13 +31,16 @@ public class SmConfiguration extends AbstractAutoConfiguration {
return properties; return properties;
} }
private X509Certificate getCertificate() { private List<X509Certificate> getCertificates() {
if (Objects.equals(getProperties().getCipher().getStoreType(), StoreType.FILE)) { 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 getProperties().getCipher().getCertificate().stream()
return PemFile.loadX509FromStream(inputStream, KonaProvider.NAME); .map(cert -> PemFile.loadX509FromStream(getClass().getClassLoader().getResourceAsStream(cert), KonaProvider.NAME))
.collect(Collectors.toList());
} }
private PrivateKey getPrivateKey() { private PrivateKey getPrivateKey() {
@ -54,7 +59,8 @@ public class SmConfiguration extends AbstractAutoConfiguration {
.channel(getChannel()) .channel(getChannel())
.httpProfile(getHttpProfile()) .httpProfile(getHttpProfile())
.privateKey(getPrivateKey()) .privateKey(getPrivateKey())
.addCertificate(getCertificate()) .certificateSerial(properties.getCipher().getChannelCertificateSerial())
.addCertificates(getCertificates())
.build(); .build();
} }
} }

View File

@ -1,6 +1,7 @@
package com.czcb.scfs.spring.boot.starter; package com.czcb.scfs.spring.boot.starter;
import com.czcb.scfs.api.core.cipher.StoreType; 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.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -84,8 +85,8 @@ class ScfsApiGatewayPropertiesTest {
ScfsApiGatewayProperties.Cipher cipher = new ScfsApiGatewayProperties.Cipher(); ScfsApiGatewayProperties.Cipher cipher = new ScfsApiGatewayProperties.Cipher();
cipher.setStoreType(StoreType.RESOURCES); cipher.setStoreType(StoreType.RESOURCES);
cipher.setChannelPrivateKey("/home/key.pem"); cipher.setChannelPrivateKey("/home/key.pem");
cipher.setChannelCertificate("/home/c1.pem"); cipher.setChannelCertificateSerial("/home/c1.pem");
cipher.setCertificate("/home/c2.pem"); cipher.setCertificate(Lists.newArrayList("/home/c2.pem"));
ScfsApiGatewayProperties properties = new ScfsApiGatewayProperties(); ScfsApiGatewayProperties properties = new ScfsApiGatewayProperties();
properties.setCipher(cipher); properties.setCipher(cipher);

View File

@ -1,6 +1,7 @@
package com.czcb.scfs.spring.boot.starter; package com.czcb.scfs.spring.boot.starter;
import com.czcb.scfs.api.core.cipher.StoreType; 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.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@ -52,8 +53,8 @@ class SmConfigurationTest {
ScfsApiGatewayProperties.Cipher cipher = new ScfsApiGatewayProperties.Cipher(); ScfsApiGatewayProperties.Cipher cipher = new ScfsApiGatewayProperties.Cipher();
cipher.setStoreType(StoreType.RESOURCES); cipher.setStoreType(StoreType.RESOURCES);
cipher.setChannelPrivateKey("/home/key.pem"); cipher.setChannelPrivateKey("/home/key.pem");
cipher.setChannelCertificate("/home/c1.pem"); cipher.setChannelCertificateSerial("/home/c1.pem");
cipher.setCertificate("/home/c2.pem"); cipher.setCertificate(Lists.list("/home/c2.pem"));
properties.setCipher(cipher); properties.setCipher(cipher);
properties.setOnline(true); properties.setOnline(true);

View File

@ -1,9 +1,10 @@
scfs.api-gateway.online=false scfs.api-gateway.online=false
scfs.api-gateway.host=http://127.0.0.1:8088/api-gateway 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=0000
scfs.api-gateway.channel.channel-no=1000 scfs.api-gateway.channel.app-no=000000
scfs.api-gateway.cipher.store-type=resources scfs.api-gateway.cipher.store-type=resources
#scfs.api-gateway.cipher.channel-private-key=rsa_channel_private_key.pem #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.certificate=rsa_channel_certificate.pem
scfs.api-gateway.cipher.channel-private-key=merchant_private_key.pem scfs.api-gateway.cipher.channel-private-key=sm2_private_key.pem
scfs.api-gateway.cipher.certificate=merchant_certificate.pem scfs.api-gateway.cipher.channel-certificate-serial=12312312879h89u8hhh89h989
scfs.api-gateway.cipher.certificate=scfs_sm2_certificate.pem

View File

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

View File

@ -1,5 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgplcULkGrRiFDra/9MywSc4Ornu/k
jdlSSXCqoHPPM0WgCgYIKoEcz1UBgi2hRANCAAS3xG2kVL1N2p71VUsFO5WyD2QCzq5SFarPpKlY
pEXCx57QeEUypZFmvzTDNpWv5y11e798SvOBSmZTFrF6CStI
-----END PRIVATE KEY-----

View File

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

View File

@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgR6jTgU+vLuT00j3QM7b/fPJ9iUGR
zZeVwr90JeVhChygCgYIKoEcz1UBgi2hRANCAAT0KcBDXLn6Zv5vsEtuDzZclr30phN++uOVaQoF
cDhhbeZlqRSIqRdg6YstCHUenN7NL2S1b1JlsWeIUxGCndZU
-----END PRIVATE KEY-----

View File

@ -31,8 +31,8 @@ class ApiGatewayTest {
@Test @Test
void testQuery() { void testQuery() {
QueryBalanceRequest queryBalanceRequest = new QueryBalanceRequest(); QueryBalanceRequest queryBalanceRequest = new QueryBalanceRequest();
queryBalanceRequest.setChannelNo("1012"); queryBalanceRequest.setChannelNo("0000");
queryBalanceRequest.setAppNo(""); queryBalanceRequest.setAppNo("000000");
queryBalanceRequest.setSerialNo(UUID.randomUUID().toString().replace("-", "")); queryBalanceRequest.setSerialNo(UUID.randomUUID().toString().replace("-", ""));
queryBalanceRequest.setAccountNo("1012230221000010"); queryBalanceRequest.setAccountNo("1012230221000010");
queryBalanceRequest.setRelationAcct("1"); queryBalanceRequest.setRelationAcct("1");

View File

@ -40,7 +40,7 @@ public class MockResponse {
SECRET_KEY + "=" + secretKey; SECRET_KEY + "=" + secretKey;
String message = buildAuth + "\n" + responseBody + "\n"; 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; return mock;
} }
} }