我正在尝试使用BouncyCastle C#库从GnuPG创建的密钥环中获取公共PGP密钥.通过使用以下代码,我将其投入了半成品.问题在于,它输出的公钥的长度约为真实密钥的一半,而最后几个字节也不同.我只是想获得真正的钥匙.
更新:有趣的是,我生成的密钥环只有一个公共密钥,但是我从bouncycastle中得到了两个.我还发现,如果将第二个密钥从末尾插入前几个字符,它将产生几乎原始的密钥.最后只有几个字符不同.那么为什么有两个键,为什么会发生呢?我想念什么?
GnuPG密钥环不兼容吗?
另请注意,此处显示的代码仅获取最后一个键.我现在将它们添加到列表中.
这是我的代码:
public static string ReadKey(string pubkeyFile)
{
string theKey;
Stream fs = File.OpenRead(pubkeyFile);
//
// Read the public key rings
//
PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(fs));
fs.Close();
foreach (PgpPublicKeyRing pgpPub in pubRings.GetKeyRings())
{
pgpPub.GetPublicKey();
foreach (PgpPublicKey pgpKey in pgpPub.GetPublicKeys())
{
//AsymmetricKeyParameter pubKey = pgpKey.GetKey();
//SubjectPublicKeyInfo k = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey);
//byte[] keyData = k.ToAsn1Object().GetDerEncoded();
//byte[] keyData = k.GetEncoded();
byte[] keyData = pgpKey.GetEncoded();
theKey = Convert.ToBase64String(keyData);
}
}
return theKey;
}
这是实际的公钥:
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.20 (MingW32)
mQENBFP2z94BCADKfQT9DGHm4y/VEAYGL7XiUavbv+aE7D2OZ2jCbwnx7BYzQBu8
63v5qYe7oH0oBOiw67VaQSjS58fSBAE8vlTkKjvRAscHJNUX9qZrQoRtpMSnrK7N
Ca9N2ptvof7ykF1TAgbxDSSnhwysVznYc7mx76BO6Qx8KChqEd0Yp3w2U89YkUqN
qdzjB7ZIhj5hDM9f4eyHwsz0uZgyqLKK5VgNj6dHVmOHZt6+RIydRC2lGfocWKM8
loPkk6GiSX9sdEm6GXxi7gV/Q3Jr0G099AFg57cWyj1eO6NC8YHLgBHwrB1IkFwi
J0x5IHZssy/XleQ1i1izc3ntWiiH24powuAhABEBAAG0H3N5bmFwczMgPHN5bmFw
czNAc2FmZS1tYWlsLm5ldD6JATkEEwECACMFAlP2z94CGwMHCwkIBwMCAQYVCAIJ
CgsEFgIDAQIeAQIXgAAKCRD944Hz1MHUYP+AB/4roauazFR5lDrJBFB0YoH4VFKM
28IJtuy6OThg3cxhqI/N74sZoxtB90QQk4lcshdpwD7CIe9TCKrnhWokIdm4N91m
TGDmW7iIeM3kcPp3mj9/7hGOetESuz9JxhBQ0aHAXYk5LdHeDKyRg1KL3JvWrJ27
fioDoLLpxxdudSd2nJLhi0hAaHKnkLVl98r37AwxTigGj+J2rN47D+UepJraf8je
eZrY/RfwKJVleF1KYPIgduwX3jdiABrI4EsZP/CdbEWTvmmkFFtD4clSMsmqaXPT
a3VeaL/saScBPL93tDsjqCddcgW28hsnhzoJ7TM78j2zNcTXZjK8/tNCDnShuQEN
BFP2z94BCADmCAMIpOp518ywUlG5Pze5HdpgGiQF26XzwxUt3mPAMXBUQ7vqRMD/
zNagPXKthp/p4t0jRoFwFwF+7CqRrxkv2Rrj5OqDD7JqETY5nfRZ0Hvfi4cPkf2g
S17SVI4LSFQ/v/sISNNiI3Bo/xvpOeK+Af087j4BEe8vjFuyzf08HCglKoL6WAp8
5+Wc2vj+7EbH61YloKKNugq34AyuNh1QYml6LI04b2KR0b/qXTW8UqLvrh4YGaOp
k80l7DpBmKgGtXn8JFfU9V3sGCscSnfzDvKjqpmtKXiJFxO2pyPCN5jRKfGMOSyA
fZ21NIrBJER/WvuIAls8Tikk+wKRKXrpABEBAAGJAR8EGAECAAkFAlP2z94CGwwA
CgkQ/eOB89TB1GDDEAf+OA9hgb3FLbEtcNvkUl9wTtLaxr9nAsBowofNEITH96hV
w4i6em9Rjg29/+4JrnDhibuhsFr/F8uKoj+iZGFw2NpXHYI6yS+BLbuVj8jOkYAy
Gq34HMNWXuS1Nr4VHOxKbKmmLu8YhdYRk2KF9fPI2Qj376C69W90R/LHByCrcCg7
xmqAvO9a8Eac7Rk+Fc+5NKVw9D1rP7MqZGgIQQoh8jLiI2MblvEEahwNxA9AYs8U
PpMD0pdo93wxXIYuKc40MF4yFL9LfpPxDnf373dbYQjk3pNThQ5RagIgLNEhRow4
5x/1wcO6FMx5a/irQXnJ2o1XYRvznBeCsoyOAYbikA==
=r3Qj
-----END PGP PUBLIC KEY BLOCK-----
这是BouncyCastle制作的NEW KEY(对不起格式设置):
mQENBFP2z94BCADKfQT9DGHm4y / VEAYGL7XiUavbv aE7D2OZ2jCbwnx7BYzQBu863v5qYe7oH0oBOiw67VaQSjS58fSBAE8vlTkKjvRAscHJNUX9qZrQoRtpMSnrK7NCa9N2ptvof7ykF1TAgbxDSSnhwysVznYc7mx76BO6Qx8KChqEd0Yp3w2U89YkUqNqdzjB7ZIhj5hDM9f4eyHwsz0uZgyqLKK5VgNj6dHVmOHZt6 RIydRC2lGfocWKM8loPkk6GiSX9sdEm6GXxi7gV / Q3Jr0G099AFg57cWyj1eO6NC8YHLgBHwrB1IkFwiJ0x5IHZssy / XleQ1i1izc3ntWiiH24powuAhABEBAAG0H3N5bmFwczMgPHN5bmFwczNAc2FmZS1tYWlsLm5ldD6JATkEEwECACMFAlP2z94CGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRD944Hz1MHUYP AB / 4roauazFR5lDrJBFB0YoH4VFKM28IJtuy6OThg3cxhqI / N74sZoxtB90QQk4lcshdpwD7CIe9TCKrnhWokIdm4N91mTGDmW7iIeM3kcPp3mj9 / 7hGOetESuz9JxhBQ0aHAXYk5LdHeDKyRg1KL3JvWrJ27fioDoLLpxxdudSd2nJLhi0hAaHKnkLVl98r37AwxTigGj J2rN47D UepJraf8jeeZrY / RfwKJVleF1KYPIgduwX3jdiABrI4EsZP / CdbEWTvmmkFFtD4clSMsmqaXPTa3VeaL / saScBPL93tDsjqCddcgW28hsnhzoJ7TM78j2zNcTXZjK8 / tNCDnShsAIAA7kBDQRT9s / eAQgA5ggDCKTqedfMsFJRuT83uR3aYBokBdul88MVLd5jwDFwVEO76kTA / 8zWoD1yrYaf6eLdI0aBcBcBfuwqka8ZL9ka4 Tqgw yahE2OZ30WdB734uHD5H9oEte0lSOC0hUP7 / 7CEjTYiNwaP8b6TnivgH9 PO4 ARHvL4xbss39PBwoJSqC lgKfOflnNr4 / uxGx tWJaCijboKt AMrjYdUGJpeiyNOG9ikdG / 6l01vFKi764eGBmjqZPNJew6QZioBrV5 / CRX1PVd7BgrHEp38w7yo6qZrSl4iRcTtqcjwjeY0SnxjDksgH2dtTSKwSREf1r7iAJbPE4pJPsCkSl66QARAQABiQEfBBgBAgAJBQJT9s / eAhsMAAoJEP3jgfPUwdRgwxAH / jgPYYG9xS2xLXDb5FJfcE7S2sa / ZwLAaMKHzRCEx / eoVcOIunpvUY4Nvf / uCa5w4Ym7obBa / xfLiqI / omRhcNjaVx2COskvgS27lY / IzpGAMhqt BzDVl7ktTa FRzsSmyppi7vGIXWEZNihfXzyNkI9 guvVvdEfyxwcgq3AoO8ZqgLzvWvBGnO0ZPhXPuTSlcPQ9az zKmRoCEEKIfIy4iNjG5bxBGocDcQPQGLPFD6TA9KXaPd8MVyGLinONDBeMhS / S36T8Q539 93W2EI5N6TU4UOUWoCICzRIUaMOOcf9cHDuhTMeWv4q0F5ydqNV2Eb85wXgrKMjgGG4pCwAgAD
还是不一样.将这两个键都放在记事本中,然后搜索“ tNCDnS”,之后它们就会改变.
感谢您的支持.我已经做得足够多了,我不想为了一些糟糕的加密而放弃整个代码.
解决方法:
您可能是BouncyCastle不太常见地使用“密钥”一词的受害者.这是BouncyCastle对三个相关术语的用法:
PgpPublicKey:这是单个数学键的公共部分,格式为PGP.它不包含任何子项.
PgpPublicKeyRing:这是带有其子密钥的加密密钥.其他程序通常将此称为PGP密钥.
PgpPublicKeyRingBundle:这是任意数量的PgpPublicKeyRings(在BouncyCastle中定义).其他程序通常将此称为公钥环(无捆绑包).
您遍历密钥环以查找所有PgpPublicKey对象.您对它们进行了解码,并以字符串的形式返回了最后一个和仅最后一个.如果将输入和输出字符串粘贴到pgpdump.net(必须将BEGIN和END标头添加到输出中),则会看到在此过程中丢失了子项.请改用PgpPublicKeyRing的GetEncoded()方法.这应该保留所有信息,并且也更容易:-).
此外,PGP的Radix编码比Base64编码略多.许多程序和库,包括BC,都忽略是否有PGP头和脚注以及是否有Radix编码所包含的CRC校验和,而不是简单的Base64.但是,GPG更严格,并且似乎不接受没有CRC校验和的ASCII防护.因此,您必须使用二进制密钥(在问题代码中为byte [] keyData)或创建适当的PGP ASCII装甲.我已经根据您的代码编辑了以下代码,以使用BC的ArmoredOutputStream实现后者:
public static string ReadKey(string pubkeyFile)
{
Stream fs = File.OpenRead(pubkeyFile);
//
// Read the public key rings
//
PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(fs));
fs.Close();
foreach (PgpPublicKeyRing pgpPub in pubRings.GetKeyRings())
{
using (MemoryStream ms = new MemoryStream())
{
using (ArmoredOutputStream aos = new ArmoredOutputStream(ms))
pgpPub.Encode(aos);
return System.Text.Encoding.ASCII.GetString(ms.ToArray());
}
}
return null;
}
编辑:以下是没有外部依赖项的完整程序.它对我有用,即输出“ Same!”.请运行该确切程序,并检查它是否输出“ Same!”.或“差异!”.如果输出“ Same!”,则可以使用它来更正自己的程序代码:
using System;
using System.IO;
using Org.BouncyCastle.Bcpg.OpenPgp;
class Program
{
private const string PGP_OVERFLOW_KEYBODY =
"mQENBFP2z94BCADKfQT9DGHm4y/VEAYGL7XiUavbv+aE7D2OZ2jCbwnx7BYzQBu8\r\n" +
"63v5qYe7oH0oBOiw67VaQSjS58fSBAE8vlTkKjvRAscHJNUX9qZrQoRtpMSnrK7N\r\n" +
"Ca9N2ptvof7ykF1TAgbxDSSnhwysVznYc7mx76BO6Qx8KChqEd0Yp3w2U89YkUqN\r\n" +
"qdzjB7ZIhj5hDM9f4eyHwsz0uZgyqLKK5VgNj6dHVmOHZt6+RIydRC2lGfocWKM8\r\n" +
"loPkk6GiSX9sdEm6GXxi7gV/Q3Jr0G099AFg57cWyj1eO6NC8YHLgBHwrB1IkFwi\r\n" +
"J0x5IHZssy/XleQ1i1izc3ntWiiH24powuAhABEBAAG0H3N5bmFwczMgPHN5bmFw\r\n" +
"czNAc2FmZS1tYWlsLm5ldD6JATkEEwECACMFAlP2z94CGwMHCwkIBwMCAQYVCAIJ\r\n" +
"CgsEFgIDAQIeAQIXgAAKCRD944Hz1MHUYP+AB/4roauazFR5lDrJBFB0YoH4VFKM\r\n" +
"28IJtuy6OThg3cxhqI/N74sZoxtB90QQk4lcshdpwD7CIe9TCKrnhWokIdm4N91m\r\n" +
"TGDmW7iIeM3kcPp3mj9/7hGOetESuz9JxhBQ0aHAXYk5LdHeDKyRg1KL3JvWrJ27\r\n" +
"fioDoLLpxxdudSd2nJLhi0hAaHKnkLVl98r37AwxTigGj+J2rN47D+UepJraf8je\r\n" +
"eZrY/RfwKJVleF1KYPIgduwX3jdiABrI4EsZP/CdbEWTvmmkFFtD4clSMsmqaXPT\r\n" +
"a3VeaL/saScBPL93tDsjqCddcgW28hsnhzoJ7TM78j2zNcTXZjK8/tNCDnShuQEN\r\n" +
"BFP2z94BCADmCAMIpOp518ywUlG5Pze5HdpgGiQF26XzwxUt3mPAMXBUQ7vqRMD/\r\n" +
"zNagPXKthp/p4t0jRoFwFwF+7CqRrxkv2Rrj5OqDD7JqETY5nfRZ0Hvfi4cPkf2g\r\n" +
"S17SVI4LSFQ/v/sISNNiI3Bo/xvpOeK+Af087j4BEe8vjFuyzf08HCglKoL6WAp8\r\n" +
"5+Wc2vj+7EbH61YloKKNugq34AyuNh1QYml6LI04b2KR0b/qXTW8UqLvrh4YGaOp\r\n" +
"k80l7DpBmKgGtXn8JFfU9V3sGCscSnfzDvKjqpmtKXiJFxO2pyPCN5jRKfGMOSyA\r\n" +
"fZ21NIrBJER/WvuIAls8Tikk+wKRKXrpABEBAAGJAR8EGAECAAkFAlP2z94CGwwA\r\n" +
"CgkQ/eOB89TB1GDDEAf+OA9hgb3FLbEtcNvkUl9wTtLaxr9nAsBowofNEITH96hV\r\n" +
"w4i6em9Rjg29/+4JrnDhibuhsFr/F8uKoj+iZGFw2NpXHYI6yS+BLbuVj8jOkYAy\r\n" +
"Gq34HMNWXuS1Nr4VHOxKbKmmLu8YhdYRk2KF9fPI2Qj376C69W90R/LHByCrcCg7\r\n" +
"xmqAvO9a8Eac7Rk+Fc+5NKVw9D1rP7MqZGgIQQoh8jLiI2MblvEEahwNxA9AYs8U\r\n" +
"PpMD0pdo93wxXIYuKc40MF4yFL9LfpPxDnf373dbYQjk3pNThQ5RagIgLNEhRow4\r\n" +
"5x/1wcO6FMx5a/irQXnJ2o1XYRvznBeCsoyOAYbikA==";
static void Main(string[] args)
{
string parsedKey = ReadKeyDirectly(PGP_OVERFLOW_KEYBODY);
if (parsedKey != PGP_OVERFLOW_KEYBODY.Replace("\r\n",""))
Console.WriteLine("Difference!");
else
Console.WriteLine("Same!");
}
public static string ReadKeyDirectly(string stringKeyData)
{
Stream fs = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(stringKeyData));
fs.Seek(0, SeekOrigin.Begin);
PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(fs));
foreach (PgpPublicKeyRing pubRing in pubRings.GetKeyRings())
return Convert.ToBase64String(pubRing.GetEncoded());
return null;
}
}