将签名转换为人类可读 (bouncycastle)
Convert signature into human readable (bouncycastle)
我想签署我用 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");
}
如何将签名格式化为人类可读的格式?
数字签名是一个非人类可读格式的字节数组,因此使用它创建 String
不会像您预期的那样工作。
如果你想要 "readable" 格式,你可以使用 BouncyCastle 的 org.bouncycastle.util.encoders.Base64
class 将其编码为 Base64(我使用的是 BouncyCastle 1.56,但以前的版本可能有Base64 转换类似 classes):
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
class强制编码(在这个例子中,我' m 使用 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
class:
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(或十六进制编码的字符串)。
我想签署我用 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");
}
如何将签名格式化为人类可读的格式?
数字签名是一个非人类可读格式的字节数组,因此使用它创建 String
不会像您预期的那样工作。
如果你想要 "readable" 格式,你可以使用 BouncyCastle 的 org.bouncycastle.util.encoders.Base64
class 将其编码为 Base64(我使用的是 BouncyCastle 1.56,但以前的版本可能有Base64 转换类似 classes):
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
class强制编码(在这个例子中,我' m 使用 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
class:
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(或十六进制编码的字符串)。