java – 使用PEM PrivateKey签名字符串
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java – 使用PEM PrivateKey签名字符串,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4655字,纯文字阅读大概需要7分钟。
内容图文
![java – 使用PEM PrivateKey签名字符串](/upload/InfoBanner/zyjiaocheng/774/92d6f496cd7b43ea9e6e4f55de6d19e9.jpg)
我有一个PEM编码的私钥,我需要用它来签名一个字符串.但是代码会因异常而崩溃:
java.security.spec.InvalidKeySpecException: java.lang.RuntimeException: error:0c0890ba:ASN.1 encoding routines:asn1_check_tlen:WRONG_TAG
关键字符串:
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI4P/+9mJV6RwCAggA
MBQGCCqGSIb3DQMHBAg/ZWGXeLHgeASCAoAhExhFxfcikmIKbFP0rgAlJuj1r999
... and so on...
hlgzM2p71FdC6NDVyyxbit/IzbimtJyhkRwOAnZ98yqtXWUEOx2v7CcUqiU8dSLA
K0PsaxNTUeUcQV+Z7yJk/8HxfE1ya3u2CgPXCZsWWmbxQG/+awE0eEnZ
-----END ENCRYPTED PRIVATE KEY-----
我尝试了很多变种,看了很多答案,但结果是一样的
编辑:在James K Polk的帮助下,我设法得到私钥字节,但现在我得到java.security.NoSuchAlgorithmException:找不到SecretKeyFactory PBES2实现.修改后的代码
private String sign(String dataString, String pkString, String privateKeyPass) throws Exception {
pkString = pkString.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "");
pkString = pkString.replace("-----END ENCRYPTED PRIVATE KEY-----", "");
pkString = pkString.replaceAll("\\s+","");
byte[] privateKeyBytes = decryptPrivateKey(Base64.decode(pkString, Base64.DEFAULT), privateKeyPass);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privateKey = kf.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
Signature instance = Signature.getInstance("SHA1withRSA");
instance.initSign(privateKey);
instance.update(dataString.getBytes(UTF_8));
return Base64.encodeToString(instance.sign(), Base64.DEFAULT);
}
public static byte[] decryptPrivateKey(byte[] key, String pass) throws Exception {
PBEKeySpec passKeySpec = new PBEKeySpec(pass.toCharArray());
EncryptedPrivateKeyInfo encryptedKey = new EncryptedPrivateKeyInfo(key);
Timber.w("encryptedKey.getAlgName(): %s", encryptedKey.getAlgName());
SecretKeyFactory keyFac = SecretKeyFactory.getInstance(encryptedKey.getAlgName());//PBES2
SecretKey passKey = keyFac.generateSecret(passKeySpec);
// Create PBE Cipher
Cipher pbeCipher = Cipher.getInstance(encryptedKey.getAlgName());
// Initialize PBE Cipher with key and parameters
pbeCipher.init(Cipher.DECRYPT_MODE, passKey, encryptedKey.getAlgParameters());
// Decrypt the private key
return pbeCipher.doFinal(encryptedKey.getEncryptedData());
}
编辑:我最终使用了http://commandlinefanatic.com/cgi-bin/showarticle.cgi?article=art050的课程:
PrivateKey privateKey = KeyImport.readPrivateKeyFile(pkFileName, privateKeyPass);
我将keyString保存到一个文件中,然后将其提供给readPrivateKeyFile
解决方法:
您的私钥是根据PKCS#8加密的,因此您需要使用EncryptedPrivateKeyInfo类. This stackoverflow question包含一个示例,说明如何检索它.我把它变成了一个更完整的例子如下:
import javax.crypto.Cipher;
import javax.crypto.EncryptedPrivateKeyInfo;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.List;
public class Main {
private static byte [] pemFileToBytes(String filename) throws IOException {
// read in PEM file, throw away the begin and end lines
List<String> pemLines = Files.readAllLines(Paths.get(filename), StandardCharsets.US_ASCII);
pemLines.remove(0);
pemLines.remove(pemLines.size() - 1);
String pem = String.join("", pemLines);
// base64 decode and return the result.
return Base64.getDecoder().decode(pem);
}
private static PrivateKey parsePrivateKey (String filename, char [] password) throws Exception{
PBEKeySpec passKeySpec = new PBEKeySpec(password); //my password
EncryptedPrivateKeyInfo encryptedKey = new EncryptedPrivateKeyInfo(pemFileToBytes(filename));
SecretKeyFactory keyFac = SecretKeyFactory.getInstance(encryptedKey.getAlgName());
SecretKey passKey = keyFac.generateSecret(passKeySpec);
// Create PBE Cipher
Cipher pbeCipher = Cipher.getInstance(encryptedKey.getAlgName());
// Initialize PBE Cipher with key and parameters
pbeCipher.init(Cipher.DECRYPT_MODE, passKey, encryptedKey.getAlgParameters());
// Decrypt the private key
byte [] encodedPrivateKey = pbeCipher.doFinal(encryptedKey.getEncryptedData());
PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedPrivateKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(privateKeySpec);
}
public static void main(String[] args) throws Exception {
PrivateKey pk = parsePrivateKey("x.pk8", "pass".toCharArray());
}
}
你最后一行,返回新的String(instance.sign(),UTF_8);没有任何意义,因为Signature.sign()返回的字节数组不可能是任何字符集中的有效字符串.如果必须将签名转换为字符串,则标准方法是对其进行base64编码.
内容总结
以上是互联网集市为您收集整理的java – 使用PEM PrivateKey签名字符串全部内容,希望文章能够帮你解决java – 使用PEM PrivateKey签名字符串所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。