【问题标题】:Convert signature into human readable (bouncycastle)将签名转换为人类可读的(bouncycastle)
【发布时间】:2017-05-12 08:47:50
【问题描述】:

我想用JFileChooser 签署我读入的文件。但是当我将它打印到终端时,我只能阅读问题标记和其他人类无法阅读的字符。 我的签名代码是:

public static void sign() throws Exception{
    byte[] file = fileChooser();

    store = KeyStore.getInstance(storeType);
    FileInputStream in = new FileInputStream(new File(storePath));
    store.load(in, storePassword);
    in.close();

    Key priv = store.getKey("test", storePassword);
    System.out.println(priv.toString() + "priv string");
    X509Certificate cert = (X509Certificate) store.getCertificate("Subject");
    ContentSigner signer = new JcaContentSignerBuilder("SHA512withRSA").build((RSAPrivateKey) priv);        

    //Sign Data
    Signature signature = Signature.getInstance("SHA512WithRSA");
    signature.initSign((RSAPrivateKey) priv);
    signature.update(file);

    //Build cms
    CMSTypedData data = new CMSProcessableByteArray(signature.sign()); 
    CMSSignedDataGenerator gen = new CMSSignedDataGenerator();

    gen.addSignerInfoGenerator(
            new JcaSignerInfoGeneratorBuilder(
                    new JcaDigestCalculatorProviderBuilder().build())
                    .build(signer, cert));

    //Get signed data
    CMSSignedData sigData = gen.generate(data, false);

    byte[] sig = (byte[]) sigData.getSignedContent().getContent();
    sig.toString();
    String content = new String(sig);
    System.out.println("Signed content: " + content + "\n");
}

如何将签名格式化为人类可读的格式?

【问题讨论】:

    标签: java format bouncycastle signature sign


    【解决方案1】:

    数字签名是一个非人类可读格式的字节数组,因此使用它创建 String 不会像您预期的那样工作。

    如果您想要“可读”格式,可以使用 BouncyCastle 的 org.bouncycastle.util.encoders.Base64 类将其编码为 Base64(我使用的是 BouncyCastle 1.56,但之前的版本可能具有类似的 Base64 转换类):

    byte[] base64ByteArray = Base64.encode(sig); // sig is your byte array
    String humanReadableString = new String(base64ByteArray); // human readable string
    

    要取回原始的sig 数组,您必须解码humanReadableString

    byte[] originalSigBytes = Base64.decode(humanReadableString.getBytes());
    // originalSigBytes will be the same as sig
    

    注意事项:如果您遇到与编码相关的任何问题,可以使用java.nio.charset.Charset 类强制编码(在本例中,我使用UTF-8,但您可以使用任何编码您的系统使用):

    // same thing as above, but using a specific encoding (UTF-8 in this case)
    String humanReadableString = new String(base64ByteArray, Charset.forName("UTF-8"));
    byte[] originalSigBytes = Base64.decode(humanReadableString.getBytes(Charset.forName("UTF-8")));
    

    另类

    如果您愿意,您还可以使用 BouncyCastle 的 org.bouncycastle.util.encoders.Hex 类转换为 Hex-encoded string(每个字节变成其值的以 16 为基数的字符串表示形式):

    byte[] hexEncodedArray = Hex.encode(sig);
    String humanReadableString = new String(hexEncodedArray, Charset.forName("UTF-8"));
    

    要找回原来的 sig 数组:

    byte[] originalSigBytes = Hex.decode(humanReadableString.getBytes(Charset.forName("UTF-8")));
    // originalSigBytes will be the same as sig
    

    还有一点:在处理密码学的东西时,我建议您始终操作byte 数组,而不是将它们转换为String。但如果必须转换为 String,则使用 Base64(或十六进制编码字符串)。

    【讨论】:

    • 两种编码方法都给我错误:Hex 类型的方法 encode(byte[]) 不适用于参数 (CMSSignedData)
    • 您必须使用byte[] sig 变量,而不是sigData
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    相关资源
    最近更新 更多