代码之家  ›  专栏  ›  技术社区  ›  hyongsop

使用PemWriter导出C#BouncyCastle EC私钥

  •  0
  • hyongsop  · 技术社区  · 9 年前

    var ecKeyPairGenerator = new ECKeyPairGenerator();
    CKeyGenerationParameters ecKeyGenParams = new ECKeyGenerationParameters(SecObjectIdentifiers.SecP384r1, new SecureRandom());
    ecKeyPairGenerator.Init(ecKeyGenParams);
    AsymmetricCipherKeyPair pair = ecKeyPairGenerator.GenerateKeyPair();
    
    string path = @"c:\tmp\test\myprivkey.pem";
    TextWriter textWriter = new StreamWriter(path);
    PemWriter pemWriter = new PemWriter(textWriter);
    // passing pair results in the private key being written out
    pemWriter.WriteObject(pair);
    pemWriter.Writer.Flush();
    pemWriter.Writer.Close();
    

    上面代码段的输出示例如下:

    -----BEGIN EC PRIVATE KEY-----
    MD4CAQEEMJvNXtTUd7A/fY/9/LSXM+Xb/6QS7GydeART/OieN3zh23Uuy0tgiS1D
    rohXMgiPvqAHBgUrgQQAIg==
    -----END EC PRIVATE KEY-----
    

    然而,当使用“openssl”和相同的EC曲线(secp384r1)执行相同的操作时,生成的PEM文件非常不同,例如:

    openssl ecparam -name secp384r1 -genkey -out mykey2.pem -noout
    
    -----BEGIN EC PRIVATE KEY-----
    MIGkAgEBBDBqCE9+AWL56cvR2/tRNdyaTIlJnfr6TbhCG+Q48w6yyKR+hE0jkeOV
    7yh1t8NwqT6gBwYFK4EEACKhZANiAAS2uLv7KG6RRBZBOecaxBz8FsMobnxgZkbQ
    8cKdL1DRym1lUDwgfX8AxOC6qkuD1k0UekpHcwiy1mSghy4640qBAKcR3mVghMVF
    77Nm8x6nwNijWZroeqhjrw268PPPuAw=
    -----END EC PRIVATE KEY-----
    

    如您所见,密钥长度非常不同,我用前者创建的P12文件没有导入到Windows证书存储中。我肯定是C#BouncyCastle出了什么问题,但看不出有什么问题(查看PemWriter和其他相关类的源代码并没有发现任何明显的错误)。

    谢谢

    2 回复  |  直到 9 年前
        1
  •  1
  •   Holger Böhnke    6 年前

    在聚会上晚了一点,您可以显式地编写私钥和公钥(也许最好使用单独的文件):

    ...
    // passing pair results in the private key being written out
    pemWriter.WriteObject(pair.Private);
    pemWriter.WriteObject(pair.Public);
    pemWriter.Writer.Flush();
    pemWriter.Writer.Close();
    

    然而,Bouncy Castle的当前版本(1.8.5)已经将公钥写入(私钥)PEM文件。因此,不需要显式编写公钥。

    此外,以下两行基本相同:

     pemWriter.WriteObject(pair);
     pemWriter.WriteObject(pair.Private);
    

    从源代码中可以看出:

    # .../BouncyCastle/.../MiscPemGenerator.cs
    private static PemObject CreatePemObject(...)
    {
      ...
      if (obj is AsymmetricCipherKeyPair)
        return MiscPemGenerator.CreatePemObject((object)
          ((AsymmetricCipherKeyPair) obj).Private,
          algorithm, password, random);
      ...
    }
    
        2
  •  -1
  •   hyongsop    9 年前

    事实证明,您可以使用私钥和公钥创建ECPrivateKeyStructure的实例,并将对象的Base64编码字符串保存到文件中,例如:

    ...
    int orderBitLength = privKeyParam.Parameters.N.BitLength;
    X962Parameters x962 = new X962Parameters(privKeyParam.PublicKeyParamSet);
    ECPrivateKeyStructure privKeyStruct = 
                        new ECPrivateKeyStructure(orderBitLength, privKeyParam.D, pubKeyInfo.PublicKeyData, x962);
    
    string header = @"-----BEGIN EC PRIVATE KEY-----";
    string privKeyStr = Convert.ToBase64String(privKeyStruct.GetDerEncoded(), 
                        Base64FormattingOptions.InsertLineBreaks);
    string tail = @"-----END EC PRIVATE KEY-----";
    
    string path = @"c:\tmp\myprivkey.pem";
    TextWriter textWriter = new StreamWriter(path);
    textWriter.WriteLine(header);
    textWriter.WriteLine(privKeyStr);
    textWriter.WriteLine(tail);
    textWriter.Flush();
    textWriter.Close();
    ...
    
    推荐文章