java 使用bc库封装ASN1结构案例

1、概要

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

2、案例 

下面主要是通过BC库,通过一些GM/T国密标准文档去实现ASN1结构封装得案例,来帮助大家封装ASN1结构代码。首先ASN1结构类型主要有三大类型。我会对分别三种使用java进行封装

  • SEQUENCE      // 基本序列结构

  • ENUMERATED // 枚举结构
  • CHIOCE            // 选择结构
  • ​​​​​​​

出除了基本结构还有常用得类型也需要大家了解一下: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
 * <p>
 * The OCSPResponseStatus enumeration.
 * <pre>
 * 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
 * }
 * </pre>
 */
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
     * <p>
     * The OCSPResponseStatus enumeration.
     * <pre>
     * 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
     * }
     * </pre>
     */
    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.
     * <pre>
     *  CertStatus ::= CHOICE {
     *                  good        [0]     IMPLICIT NULL,
     *                  revoked     [1]     IMPLICIT RevokedInfo,
     *                  unknown     [2]     IMPLICIT UnknownInfo }
     * </pre>
     */
    public ASN1Primitive toASN1Primitive()
    {
        return new DERTaggedObject(false, tagNo, value);
    }
}

猜你喜欢

转载自blog.csdn.net/m0_43432638/article/details/127447616