导出 ASN.1 格式,然后使用 Base64 编码 JAVA

Export ASN.1 format, then encode with Base64 JAVA

我想制作一个自定义的 ASN.1 结构,它由 3 个 PrintableString 和 1 个 OctetString 组成。我正在使用 BouncyCastle 框架来处理这个问题。

所以我在我的class中设置了需要的参数,现在我必须return这个ASN.1格式的结构,然后用Base64编码(它的参数是byte[] ), 然后转换为 PEM 格式。

所以我的问题是,我必须从方法 getASN1format() 中 return 什么类型的对象?

我的代码:

import org.bouncycastle.asn1.*;
import java.io.IOException;

public class ASN1Handshake1 implements ASN1Encodable {
    private DERPrintableString A, B, ID_PASS;
    private ASN1OctetString ID_K;

    public ASN1Handshake1(String A, String B, String ID_K, String ID_PASS, TTP TTPs ) throws IOException {
        this.A = new DERPrintableString(A);
        this.B = new DERPrintableString(B);
        this.ID_K = new DEROctetString(ID_K.getBytes());
        this.ID_PASS = new DERPrintableString(ID_PASS);
    }

    public ?? getASN1format(){
        //TODO
    }

    @Override
    public ASN1Primitive toASN1Primitive() {
        return null;
    }
}

我正在为这段代码使用 Bouncy Castle 1.57 (bcprov-jdk15on)。

首先,请记住 ASN.1 本身并不是一种格式 ,它是一种 description language that defines a structure, and PEM is a format that uses base 64. Many cryptography standards use ASN.1 to define their data structures, and PEM or DER (Distinguished Encoding Rules) 序列化这些结构的格式。

所以,如果你想获取ASN.1结构并将其格式化为base64,你可以如下操作。您不需要 getASN1format 方法,只需使用现有的方法即可。

ASN.1 结构中的字段不能只是 "loose"。所以我决定把它们放在一个序列中(使用 org.bouncycastle.asn1.DERSequence class),这是存储结构体字段的最佳选择。我按照声明的顺序排列它们,当然你可以选择任何你想要的顺序。

我还更改了变量名称以遵循 Java's code conventions(名称以小写字母开头)。所以class代码是:

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERPrintableString;
import org.bouncycastle.asn1.DERSequence;

public class ASN1Handshake1 extends ASN1Object {

    private DERPrintableString a, b, idPass;

    private ASN1OctetString idK;

    // removed TTPs parameter (it wasn't using it)
    public ASN1Handshake1(String a, String b, String idK, String idPass) {
        this.a = new DERPrintableString(a);
        this.b = new DERPrintableString(b);
        this.idK = new DEROctetString(idK.getBytes());
        this.idPass = new DERPrintableString(idPass);
    }

    // returns a DERSequence containing all the fields
    @Override
    public ASN1Primitive toASN1Primitive() {
        ASN1Encodable[] v = new ASN1Encodable[] { this.a, this.b, this.idK, this.idPass };
        return new DERSequence(v);
    }
}

创建握手 object 并将其转换为 base64(下面的代码不处理异常,因此相应地添加 try/catch 块):

import org.bouncycastle.util.encoders.Base64;

// create handshake object with some sample data
ASN1Handshake1 handshake = new ASN1Handshake1("a", "b", "ID_K", "ID_PASS");

// convert it to base64
String base64String = new String(Base64.encode(handshake.getEncoded()));
System.out.println(base64String);

这将以 base64 格式输出握手结构:

MBUTAWETAWIEBElEX0sTB0lEX1BBU1M=

请注意,这不是完整的 PEM(headers 类似于 -----BEGIN CERTIFICATE-----),因为您的自定义结构不是预定义的标准。因此,您必须继续使用这个 base64 通用字符串。

要检查 base64 字符串是否包含 ASN.1 序列,只需执行以下操作:

// read from base64 String
ASN1Sequence seq = (ASN1Sequence) DERSequence.fromByteArray(Base64.decode(base64String.getBytes()));
int n = seq.size();
for (int i = 0; i < n; i++) {
    ASN1Encodable obj = seq.getObjectAt(i);
    if (obj instanceof DEROctetString) {
        System.out.println(new String(((DEROctetString) obj).getOctets()));
    } else {
        System.out.println(obj);
    }
}

输出为:

a
b
ID_K
ID_PASS