1、概要
在案例之前,我们需要了解一下啥是ASN1?ASN.1抽象语法标记是一种 ISO/ITU-T 标准,描述了一种对数据进行表示、编码、传输和解码的数据格式。它提供了一整套正规的格式用于描述对象的结构,而不管语言上如何执行及这些数据的具体指代,也不用去管到底是什么样的应用程序。也就是说不管C语言、Java、Python都是能够将ASN1编码结构进行相互转化。其次简单说一下bc这个库是啥?BC全名是BouncyCastle,他是一个第三方密码算法相关得库,包括国密算法SM2,对称,非对称等等。
2、案例
下面主要是通过BC库,通过一些GM/T国密标准文档去实现ASN1结构封装得案例,来帮助大家封装ASN1结构代码。首先ASN1结构类型主要有三大类型。我会对分别三种使用java进行封装
SEQUENCE // 基本序列结构

出除了基本结构还有常用得类型也需要大家了解一下:Extensions、ASN1OctetString、ASN1Integer、ASN1GeneralizedTime、ASN1BitString规律就是一般都是根据下面得结构属性名称加一个ASN1就是这个类型(但是实际中也是需要自己去试)。

- public class AppUserInfo extends ASN1Object {
- private ASN1Integer userCertNo;
- private SubjectPublicKeyInfo userPubKey;
- private ASN1GeneralizedTime notBefore;
- private ASN1GeneralizedTime notAfter;
- private ASN1OctetString userName;
- private ASN1IA5String dsCode;
- private ASN1IA5String extendInfo;
-
- private static final int TAG_USER_NAME = 0;
- private static final int TAG_DS_CODE = 1;
- private static final int TAG_EXTEND_INFO = 2;
-
- public static AppUserInfo getInstance(ASN1TaggedObject obj, boolean explicit)
- {
- return getInstance(ASN1Sequence.getInstance(obj, explicit));
- }
-
- public static AppUserInfo getInstance(Object obj) {
- if (obj instanceof AppUserInfo) {
- return (AppUserInfo) obj;
- } else {
- return obj != null ? new AppUserInfo(ASN1Sequence.getInstance(obj)) : null;
- }
- }
-
- public AppUserInfo(ASN1Sequence sequence) {
- if (sequence.size() == 7) {
- this.userCertNo = ASN1Integer.getInstance(sequence.getObjectAt(0));
- this.userPubKey = SubjectPublicKeyInfo.getInstance(sequence.getObjectAt(1));
- this.notBefore = ASN1GeneralizedTime.getInstance(sequence.getObjectAt(2));
- this.notAfter = ASN1GeneralizedTime.getInstance(sequence.getObjectAt(3));
- this.userName = ASN1OctetString.getInstance(sequence.getObjectAt(4));
- this.dsCode = ASN1IA5String.getInstance(sequence.getObjectAt(5));
- this.extendInfo = ASN1IA5String.getInstance(sequence.getObjectAt(6));
-
- } else {
- throw new IllegalArgumentException("Bad sequence size: " + sequence.size());
- }
- }
-
- @Override
- public ASN1Primitive toASN1Primitive() {
- ASN1EncodableVector vec = new ASN1EncodableVector(7);
- vec.add(this.userCertNo);
- vec.add(this.userPubKey);
- vec.add(this.notBefore);
- vec.add(this.notAfter);
- vec.add(this.userName);
- vec.add(this.dsCode);
- vec.add(this.extendInfo);
-
- return new DERSequence(vec);
- }
-
- }

- import java.math.BigInteger;
-
- import org.bouncycastle.asn1.ASN1Enumerated;
- import org.bouncycastle.asn1.ASN1Object;
- import org.bouncycastle.asn1.ASN1Primitive;
-
-
- /**
- * OCSP RFC 2560, RFC 6960
- *
- * The OCSPResponseStatus enumeration.
- *
- * OCSPResponseStatus ::= ENUMERATED {
- * successful (0), --Response has valid confirmations
- * malformedRequest (1), --Illegal confirmation request
- * internalError (2), --Internal error in issuer
- * tryLater (3), --Try again later
- * --(4) is not used
- * sigRequired (5), --Must sign the request
- * unauthorized (6) --Request unauthorized
- * }
- *
- */
- public class OCSPResponseStatus
- extends ASN1Object
- {
- public static final int SUCCESSFUL = 0;
- public static final int MALFORMED_REQUEST = 1;
- public static final int INTERNAL_ERROR = 2;
- public static final int TRY_LATER = 3;
- public static final int SIG_REQUIRED = 5;
- public static final int UNAUTHORIZED = 6;
-
- private ASN1Enumerated value;
-
- /**
- * RFC 2560, RFC 6960
- *
- * The OCSPResponseStatus enumeration.
- *
- * OCSPResponseStatus ::= ENUMERATED {
- * successful (0), --Response has valid confirmations
- * malformedRequest (1), --Illegal confirmation request
- * internalError (2), --Internal error in issuer
- * tryLater (3), --Try again later
- * --(4) is not used
- * sigRequired (5), --Must sign the request
- * unauthorized (6) --Request unauthorized
- * }
- *
- */
- public OCSPResponseStatus(
- int value)
- {
- this(new ASN1Enumerated(value));
- }
-
- private OCSPResponseStatus(
- ASN1Enumerated value)
- {
- this.value = value;
- }
-
- public static OCSPResponseStatus getInstance(
- Object obj)
- {
- if (obj instanceof OCSPResponseStatus)
- {
- return (OCSPResponseStatus)obj;
- }
- else if (obj != null)
- {
- return new OCSPResponseStatus(ASN1Enumerated.getInstance(obj));
- }
-
- return null;
- }
-
- public int getIntValue()
- {
- return value.intValueExact();
- }
-
- public BigInteger getValue()
- {
- return value.getValue();
- }
-
- public ASN1Primitive toASN1Primitive()
- {
- return value;
- }
- }

-
- import org.bouncycastle.asn1.ASN1Choice;
- import org.bouncycastle.asn1.ASN1Encodable;
- import org.bouncycastle.asn1.ASN1Null;
- import org.bouncycastle.asn1.ASN1Object;
- import org.bouncycastle.asn1.ASN1Primitive;
- import org.bouncycastle.asn1.ASN1TaggedObject;
- import org.bouncycastle.asn1.ASN1Util;
- import org.bouncycastle.asn1.DERNull;
- import org.bouncycastle.asn1.DERTaggedObject;
-
- public class CertStatus
- extends ASN1Object
- implements ASN1Choice
- {
- private int tagNo;
- private ASN1Encodable value;
-
- /**
- * create a CertStatus object with a tag of zero.
- */
- public CertStatus()
- {
- tagNo = 0;
- value = DERNull.INSTANCE;
- }
-
- public CertStatus(
- RevokedInfo info)
- {
- tagNo = 1;
- value = info;
- }
-
- public CertStatus(
- int tagNo,
- ASN1Encodable value)
- {
- this.tagNo = tagNo;
- this.value = value;
- }
-
- private CertStatus(
- ASN1TaggedObject choice)
- {
- int tagNo = choice.getTagNo();
-
- switch (tagNo)
- {
- case 0:
- value = ASN1Null.getInstance(choice, false);
- break;
- case 1:
- value = RevokedInfo.getInstance(choice, false);
- break;
- case 2:
- // UnknownInfo ::= NULL
- value = ASN1Null.getInstance(choice, false);
- break;
- default:
- throw new IllegalArgumentException("Unknown tag encountered: " + ASN1Util.getTagText(choice));
- }
-
- this.tagNo = tagNo;
- }
-
- public static CertStatus getInstance(
- Object obj)
- {
- if (obj == null || obj instanceof CertStatus)
- {
- return (CertStatus)obj;
- }
- else if (obj instanceof ASN1TaggedObject)
- {
- return new CertStatus((ASN1TaggedObject)obj);
- }
-
- throw new IllegalArgumentException("unknown object in factory: " + obj.getClass().getName());
- }
-
- public static CertStatus getInstance(
- ASN1TaggedObject obj,
- boolean explicit)
- {
- return getInstance(obj.getObject()); // must be explicitly tagged
- }
-
- public int getTagNo()
- {
- return tagNo;
- }
-
- public ASN1Encodable getStatus()
- {
- return value;
- }
-
- /**
- * Produce an object suitable for an ASN1OutputStream.
- *
- * CertStatus ::= CHOICE {
- * good [0] IMPLICIT NULL,
- * revoked [1] IMPLICIT RevokedInfo,
- * unknown [2] IMPLICIT UnknownInfo }
- *
- */
- public ASN1Primitive toASN1Primitive()
- {
- return new DERTaggedObject(false, tagNo, value);
- }
- }