Skip to content

Commit

Permalink
增加了电子签章验证测试用例
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] committed Apr 22, 2020
1 parent 263df4b commit a9a6697
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,39 +1,35 @@
package org.ofdrw.sign.verify.container;

import org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.ofdrw.core.signatures.SigType;
import org.ofdrw.sign.verify.SignedDataValidateContainer;
import org.ofdrw.sign.verify.exceptions.InvalidSignedValueException;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;

/**
* 数字签名验证容器
*
* @author 权观宇
* @since 2020-04-22 03:22:22
*/
public class DigitalSignContainer implements SignedDataValidateContainer {
public class DigitalValidateContainer implements SignedDataValidateContainer {
/**
* 验证使用的公钥
*/
public PublicKey pk;

public DigitalSignContainer(PublicKey pk) {
public DigitalValidateContainer(PublicKey pk) {
if (pk == null) {
throw new IllegalArgumentException("验证使用的公钥参数(pk)不能为空");
}
this.pk = pk;
}

public DigitalSignContainer(Certificate certificate) {
public DigitalValidateContainer(Certificate certificate) {
this(certificate.getPublicKey());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package org.ofdrw.sign.verify.container;

import org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory;
import org.bouncycastle.jcajce.provider.digest.SM3;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.ofdrw.core.signatures.SigType;

import org.ofdrw.gm.ses.v1.SES_Signature;
import org.ofdrw.gm.ses.v1.TBS_Sign;
import org.ofdrw.sign.verify.SignedDataValidateContainer;
import org.ofdrw.sign.verify.exceptions.InvalidSignedValueException;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.Signature;
import java.security.cert.Certificate;
import java.util.Arrays;

/**
* 《《GM/T 0031-2014 安全电子签章密码技术规范》 电子印章数据验证
* <p>
* 注意:仅用于测试,电子签章验证请使用符合国家规范的流程进行!
*
* @author 权观宇
* @since 2020-04-22 22:56:23
*/
public class SESV1ValidateContainer implements SignedDataValidateContainer {

@Override
public void validate(SigType type,
String signAlgName,
byte[] tbsContent,
byte[] signedValue)
throws InvalidSignedValueException, IOException, GeneralSecurityException {
if (type == SigType.Sign) {
throw new IllegalArgumentException("签名类型(type)必须是 Seal,不支持电子印章验证");
}

// 计算原文摘要
MessageDigest md = new SM3.Digest();
byte[] actualDataHash = md.digest(tbsContent);

SES_Signature sesSignature = SES_Signature.getInstance(signedValue);
TBS_Sign toSign = sesSignature.getToSign();
byte[] expectDataHash = toSign.getDataHash().getOctets();


// 比较原文摘要
if (!Arrays.equals(actualDataHash, expectDataHash)) {
throw new InvalidSignedValueException("Signature.xml 文件被篡改,电子签章失效。("
+ toSign.getPropertyInfo().getString() + ")");
}

// 预期的电子签章数据,签章值
byte[] expSigVal = sesSignature.getSignature().getOctets();

Signature sg = Signature.getInstance( toSign.getSignatureAlgorithm().getId(),
new BouncyCastleProvider());
byte[] certDER = toSign.getCert().getOctets();
// 构造证书对象
Certificate signCert = new CertificateFactory()
.engineGenerateCertificate(new ByteArrayInputStream(certDER));
sg.initVerify(signCert);
sg.update(toSign.getEncoded("DER"));
if (!sg.verify(expSigVal)) {
throw new InvalidSignedValueException("电子签章数据签名值不匹配,电子签章数据失效。");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package org.ofdrw.sign.verify.container;

import org.bouncycastle.asn1.ASN1BitString;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory;
import org.bouncycastle.jcajce.provider.digest.SM3;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.ofdrw.core.signatures.SigType;
import org.ofdrw.gm.ses.v4.SES_Signature;
import org.ofdrw.gm.ses.v4.TBS_Sign;
import org.ofdrw.sign.verify.SignedDataValidateContainer;
import org.ofdrw.sign.verify.exceptions.InvalidSignedValueException;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.Signature;
import java.security.cert.Certificate;
import java.util.Arrays;

/**
* 《GB/T 38540-2020 信息安全技术 安全电子签章密码技术规范》 电子印章数据验证
* <p>
* 注意:仅用于测试,电子签章验证请使用符合国家规范的流程进行!
*
* @author 权观宇
* @since 2020-04-22 22:56:23
*/
public class SESV4ValidateContainer implements SignedDataValidateContainer {

@Override
public void validate(SigType type,
String signAlgName,
byte[] tbsContent,
byte[] signedValue)
throws InvalidSignedValueException, IOException, GeneralSecurityException {
if (type == SigType.Sign) {
throw new IllegalArgumentException("签名类型(type)必须是 Seal,不支持电子印章验证");
}

// 计算原文摘要
MessageDigest md = new SM3.Digest();
byte[] actualDataHash = md.digest(tbsContent);

SES_Signature sesSignature = SES_Signature.getInstance(signedValue);
TBS_Sign toSign = sesSignature.getToSign();
byte[] expectDataHash = toSign.getDataHash().getOctets();

// 比较原文摘要
if (!Arrays.equals(actualDataHash, expectDataHash)) {
throw new InvalidSignedValueException("Signature.xml 文件被篡改,电子签章失效。("
+ toSign.getPropertyInfo().getString() + ")");
}

// 预期的电子签章数据,签章值
byte[] expSigVal = sesSignature.getSignature().getOctets();
Signature sg = Signature.getInstance(sesSignature.getSignatureAlgID().getId(),
new BouncyCastleProvider());
byte[] certDER = sesSignature.getCert().getOctets();
// 构造证书对象
Certificate signCert = new CertificateFactory()
.engineGenerateCertificate(new ByteArrayInputStream(certDER));
sg.initVerify(signCert);
sg.update(toSign.getEncoded("DER"));
if (!sg.verify(expSigVal)) {
throw new InvalidSignedValueException("电子签章数据签名值不匹配,电子签章数据失效。");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.ofdrw.sign.verify.container;

import org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory;
import org.junit.jupiter.api.Test;
import org.ofdrw.gm.cert.PKCS12Tools;
import org.ofdrw.reader.OFDReader;
Expand All @@ -12,12 +11,10 @@
import java.security.GeneralSecurityException;
import java.security.cert.Certificate;

import static org.junit.jupiter.api.Assertions.*;

/**
* 数字电子签章验证
*/
class DigitalSignContainerTest {
class DigitalValidateContainerTest {

@Test
void validate() throws IOException, GeneralSecurityException {
Expand All @@ -30,7 +27,7 @@ void validate() throws IOException, GeneralSecurityException {

try (OFDReader reader = new OFDReader(src);
OFDValidator validator = new OFDValidator(reader)) {
DigitalSignContainer dsc = new DigitalSignContainer(cert);
DigitalValidateContainer dsc = new DigitalValidateContainer(cert);
validator.setValidator(dsc);
validator.exeValidate();
System.out.println(">> 验证通过");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.ofdrw.sign.verify.container;

import org.junit.jupiter.api.Test;
import org.ofdrw.reader.OFDReader;
import org.ofdrw.sign.verify.OFDValidator;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;

import static org.junit.jupiter.api.Assertions.*;

/**
* @author 权观宇
* @since 2020-04-22 23:37:16
*/
class SESV1ValidateContainerTest {
@Test
void validate() throws IOException, GeneralSecurityException {
Path src = Paths.get("target/SESV1SignDoc.ofd");

try (OFDReader reader = new OFDReader(src);
OFDValidator validator = new OFDValidator(reader)) {
validator.setValidator(new SESV1ValidateContainer());
validator.exeValidate();
System.out.println(">> 验证通过");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.ofdrw.sign.verify.container;

import org.junit.jupiter.api.Test;
import org.ofdrw.reader.OFDReader;
import org.ofdrw.sign.verify.OFDValidator;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;

import static org.junit.jupiter.api.Assertions.*;

/**
* @author 权观宇
* @since 2020-04-22 23:10:01
*/
class SESV4ValidateContainerTest {


@Test
void validate() throws IOException, GeneralSecurityException {
Path src = Paths.get("target/SESV4SignDoc.ofd");

try (OFDReader reader = new OFDReader(src);
OFDValidator validator = new OFDValidator(reader)) {
validator.setValidator(new SESV4ValidateContainer());
validator.exeValidate();
System.out.println(">> 验证通过");
}
}
}

0 comments on commit a9a6697

Please sign in to comment.