java– 使用PEM PrivateKey签名字符串

java– 使用PEM PrivateKey签名字符串,第1张

概述我有一个PEM编码的私钥,我需要用它来签名一个字符串.但是代码会因异常而崩溃:java.security.spec.InvalidKeySpecException:java.lang.RuntimeException:error:0c0890ba:ASN.1encodingroutines:asn1_check_tlen:WRONG_TAG关键字符串:-----BEGINENCRYPTEDPRIVATEKEY-----

我有一个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());    }

编辑:我最终使用了@L_419_0@的课程:

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签名字符串所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1117395.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-29
下一篇2022-05-29

发表评论

登录后才能评论

评论列表(0条)

    保存