我的应用程序以PEM格式存储私钥,现有代码适用于RSA密钥但我试图切换到EC密钥并且存在问题.密钥恢复似乎有效,并且恢复密钥上的equals方法对原始密钥返回true,但原始密钥上的getAlgorithm()返回“EC”并返回恢复密钥“ECDSA”.算法中的差异后来导致问题,因为它与相应公钥的算法不匹配.

我做错了什么或者这是PEM解析器中的错误?

这是一个演示问题的测试程序:

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;

import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.PEMWriter;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.immutify.janus.keytool.KeyToolUtils;

public class TestPrivateKeyRecovery
{
    private static final String KEY_ALGORITHM           = "EC";
    private static final String SIGNATURE_ALGORITHM     = "SHA512withECDSA";
    private static final String PROVIDER                = "BC";
    private static final String CURVE_NAME              = "secp521r1";
    private static final String WRAPPING_CIPHER_SPEC    = "ECIESwithAES";

    private ECGenParameterSpec  ecGenSpec;
    private KeyPairGenerator    keyGen_;
    private SecureRandom        rand_;

    public void run()
    {
        try
        {
            rand_       = new SecureRandom();
            ecGenSpec   = new ECGenParameterSpec(CURVE_NAME);
            keyGen_     = KeyPairGenerator.getInstance(KEY_ALGORITHM,PROVIDER);

            keyGen_.initialize(ecGenSpec,rand_);


            PrivateKey privateKey = keyGen_.generateKeyPair().getPrivate();





            String der = privateKeyToDER(privateKey);

            PrivateKey recoveredKey = privateKeyFromDER(der);

            System.out.println("privateKey=" + privateKey);
            System.out.println("privateKey.getAlgorithm()=" + privateKey.getAlgorithm());
            System.out.println("der=" + der);
            System.out.println("recoveredKey=" + privateKey);
            System.out.println("recoveredKey.getAlgorithm()=" + recoveredKey.getAlgorithm());
            System.out.println();

            if(privateKey.equals(recoveredKey))
                System.out.println("Key recovery ok");
            else
                System.err.println("Private key recovery Failed");

            if(privateKey.getAlgorithm().equals(recoveredKey.getAlgorithm()))
                System.out.println("Key algorithm ok");
            else
                System.err.println("Key algorithms do not match");
        }
        catch(Exception e)
        {
            e.printstacktrace();
        }
    }

    public static   String      privateKeyToDER(PrivateKey key) throws IOException
    {
        ByteArrayOutputStream   bos = new ByteArrayOutputStream();
        PEMWriter               pemWriter = new PEMWriter(new OutputStreamWriter(bos));

        pemWriter.writeObject(key);

        pemWriter.close();

        return new String(bos.toByteArray());
    }

    public static   PrivateKey      privateKeyFromDER(String der) throws IOException
    {
        StringReader            reader = new StringReader(der);
        PEMParser               pemParser = new PEMParser(reader);

        try
        {
            Object o = pemParser.readobject();

            if (o == null || !(o instanceof PEMKeyPair))
            {
                throw new IOException("Not an OpenSSL key");
            }

            KeyPair kp = new JcaPEMKeyConverter().setProvider("BC").getKeyPair((PEMKeyPair)o);
            return kp.getPrivate();
        }
        finally
        {
            pemParser.close();
        }
    }
}

测试程序的输出是:

privateKey=EC Private Key
             S: 13d19928468d14fabb9235a81fc1ec706ff5413a70a760b63e07d45a5d04a2f18425ef735500190291aacaf58c92306acd87fa01a47d907d5d3fc01531180353146

privateKey.getAlgorithm()=EC
der=-----BEGIN EC PRIVATE KEY-----
MIHcAgEBBEIBPRmShGjRT6u5I1qB/B7HBv9UE6cKdgtj4H1FpdBKLxhcxvc1UAGQ
KRqsr1jJIwas2H+gGkfZB9XT/AFTEYA1MUagBwYFK4EEACOhgYkDgYYABAFN5ZcE
zg9fV13u57ffwyN9bm9Wa9Pe0MtL2cd5CW2ku4mWzgS5m8IfNMAw2QMah5Z9fuXW
1fGJgUx1RsC09R6legFTgymlbqt+CaPhNsJkr12cjyzhT1NxR6uEzMUtBcYxqLHy
ANkhHmvAk221//YIRIWix7ZlrsRrs+iYrpWw4bMt9A==
-----END EC PRIVATE KEY-----

recoveredKey=EC Private Key
             S: 13d19928468d14fabb9235a81fc1ec706ff5413a70a760b63e07d45a5d04a2f18425ef735500190291aacaf58c92306acd87fa01a47d907d5d3fc01531180353146

recoveredKey.getAlgorithm()=ECDSA

Key recovery ok
Key algorithms do not match

解决方法

问题不是PEMParser而是JcaPEMKeyConverter将EC密钥视为ECDSA的密钥:
algorithms.put(X9ObjectIdentifiers.id_ecpublicKey,"ECDSA");
...
private KeyFactory getKeyFactory(AlgorithmIdentifier algid)
throws NoSuchAlgorithmException,NoSuchProviderException
{
  ASN1ObjectIdentifier algorithm = algid.getAlgorithm();
  String algName = (String)algorithms.get(algorithm);
...

算法标识符是id-ecpublicKey,它也用于ECDSA密钥,因此算法选择在这里不是唯一的,并且BC devs可能选择ECDSA作为最合适的选择.您可以使用自己的KeyFactory执行类似JcaPEMKeyConverter的操作,但为EC键选择正确的算法.

java – 使用BouncyCastle从PEM格式恢复EC私钥的更多相关文章

  1. ios – 如何在iphone中生成推送通知的pem文件?

    使用这个link生成pem文件进行推送通知,但是我不明白以下步骤…

  2. 一个适用于多个iOS应用程序的APNS证书

    你有什么其他建议可以解决这个问题吗?解决方法不可以为多个应用使用相同的PEM文件.您需要为每个应用程序创建单独的PEM文件.因为苹果推送通知服务器无法通过一个PEM证书来识别您的不同应用程序.

  3. html中select语句读取mysql表中内容

  4. Java中基于Aspectwerkz的AOP

    满足这些要求的框架不止一个,例如JBossAOP、Nanning、Aspectwerkz。Aspectwerkz由JonasBoner和AlexandreVasseur创建,它是目前最快速、功能最丰富的框架之一。Aspectwerkz最令人感兴趣的特性之一是它能够以两种不同的模式运行:联机模式和脱机模式。⑶将Aspectwerkz加入到PATH环境变量,即设置setPATH=%PATH%;%ASPECTWERKZ_HOME%inaspectwerkz⑷下载本文的示范程序,将它放入%TOMCAT_HOME%

  5. PHP中在数据库中保存Checkbox数据(2)

    其中"get_checkbox_labels"查询表const_skills并且返回一个对象数组,每一个对象有一个id值和相应的技能名称。我们传送这个数组和其它一些参数给"make_checkbox_html",这个函数将返回一个字串,用来生成checkbox的html代码。现在我们把这个字串插入html文件来生成我们需要的包含有各种技能选择的表单。注意我并没有传送变量$checked给"make_checkbox_html",这个参数是一个我们要显示的checked的对象数组。

  6. Eclipse中使用ANT

    另外,使用ant的过程实际上对构建进行了文档化,它是无关于IDE的,想象一下,你的同事中可能三分之一在用JbuilderX,三分之一用eclipse,还有一些是别的。本人使用eclipse3.0.1,以前的构建和发布工作都由myeclipse插件作了,趁周末实践了一下手动构建,记此备忘。dlist-输出的jar或war当然,我们要建一个build.xml,eclipse中会出现一个蚂蚁的小图标,一般这个文件建立后,下一个项目简单的copy过去,稍加改动就可以了。

  7. Android签名文件转化为pk8和pem的实现

    这篇文章主要介绍了Android签名文件转化为pk8和pem的实现,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  8. JSP由浅入深(7)—— JSP Directives

    在前面的教程中,我们已经使用了java.util.Date。其实,在JSPs中也可以使用import语句,但是它的语法跟普通的Java是有些差别的。下面给出一个例子:Hello!Thetimeisnow上面的代码中第一行我们调用了一个“directive”。这个JSP“directive”是以

  9. 对javascript和select部件的结合运用

    php//对Javascript和select部件的结合运用//在写程序的过程,我想实现在select对象选中选项后,//不需要提交按钮,而直接触发动作,且在动作发生后//的页面中要保持所选择的选项。经过形容,终于通过//使用Javascript及select对象的onchange属性及//value值而实现了这种功能。>

  10. php的header和asp中的redirect比较

    >我们发现它重定向b.php.原来在asp中执行redirect后不会再执行后面的代码.而php在执行header后,继续执行下面的代码.在这方面上php中的header重定向不如asp中的重定向.有时我们要重定向后,不能执行后面的代码:一般地我们用if(...)header;else{...}但是我们可以简单的用下面的方法:if(...){header;break;}

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部