使用PEM PrivateKey签名字符串

编程入门 行业动态 更新时间:2024-10-19 00:22:15
本文介绍了使用PEM PrivateKey签名字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我有一个PEM编码的私钥,我需要用它签名一个字符串.但是代码不断崩溃,并带有异常:

I have a PEM-encoded private key and I need to sign a string with it. But the code keeps crashing with exception:

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-----

我尝试了许多变体,通过许多答案进行了研究,但结果却是相同的

I've tried many variants, looked through many answers, but the results were the same

在James K Polk的帮助下,我设法获得了私钥字节,但是现在我得到了 java.security.NoSuchAlgorithmException:未找到SecretKeyFactory PBES2实现.修改后的代码:

with James K Polk's help I've managed to get private key bytes, but now I get java.security.NoSuchAlgorithmException: SecretKeyFactory PBES2 implementation not found. Modified code:

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()); }

我最终使用了 commandlinefanatic/cgi-bin/showarticle.cgi?article=art050 :

PrivateKey privateKey = KeyImport.readPrivateKeyFile(pkFileName, privateKeyPass);

我将keyString保存到文件中,然后将其输入到readPrivateKeyFile

I save keyString into a file and then feed it to readPrivateKeyFile

推荐答案

您的私钥已根据PKCS#8进行了加密,因此您需要使用 EncryptedPrivateKeyInfo 类.此stackoverflow问题包含一个显示如何检索它的示例.我已将其变成下面更完整的示例:

Your private key is encrypted according PKCS#8, so you need to use the EncryptedPrivateKeyInfo class among others. This stackoverflow question contains an example showing how to retrieve it. I have turned it into a more complete example below:

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编码.

You last line, return new String(instance.sign(), UTF_8); doesn't make any sense as Signature.sign() returns an array of bytes that is not likely to be a valid string in any character set. If you must convert the signature to a string then the standard way is to base64 encode it.

更多推荐

使用PEM PrivateKey签名字符串

本文发布于:2023-11-08 20:22:59,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1570364.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:字符串   PEM   PrivateKey

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!