Syn*_*ps3 3 c# encryption bouncycastle pgp openpgp
我正在尝试从 GnuPG 使用 BouncyCastle C# 库创建的密钥环获取公共 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;
}
Run Code Online (Sandbox Code Playgroud)
这是实际的公钥:
-----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-----
Run Code Online (Sandbox Code Playgroud)
这是 BouncyCastle 制作的新密钥(抱歉无法帮助格式化):
mQENBFP2z94BCADKfQT9DGHm4y/VEAYGL7XiUavbv+ae7D2OZ2jCbwnx7BYzQBu863v5qYe7oH0oBOiw67VaQSjS58fSBAE8vlTkKjvRAscHJNUX9qZrQoRtpMSnrk7NCa9N2ptvof7ykF1标签gbxDSSnhwysVznYc7mx76BO6Qx8KChqEd0Yp3w2U89YkUqNqdzjB7ZIhj5hDM9f4eyHwsz0uZgyqLKK5VgNj6dHVmOHZt6+RIydRC2lGfocWKM8loPkk6GiSX9sdEm6GXxi7gV/Q3Jr0 G099AFg57cWyj1eO6NC8YHLgBHwrB1IkFwiJ0x5IHZssy/XleQ1i1izc3ntWiiH24powuAhABEBAAG0H3N5bmFwczMgPHN5bmFwczNAc2FmZS1tYWlsLm5ldD6JATkeewECACMFAlP2z94CGwMHCwkIBwMC AQYVCAIJCgsEFgIDAQIeAQIXgAAKCRD944Hz1MHUYP+AB/4roauazFR5lDrJBFB0YoH4VFKM28IJtuy6OThg3cxhqI/N74sZoxtB90QQk4lcshdpwD7CIe9TCKrnhWokIdm4N91mTGDmW7iIeM3kcPp3m j9/7hGOetESuz9JxhBQ0aHAXYk5LdHeDKyRg1KL3JvWrJ27fioDoLLpxxdudSd2nJLhi0hAaHKnkLVl98r37AwxTigGj+J2rN47D+UepJraf8jeeZrY/RfwKJVleF1KYPIgduwX3jdiABrI4EsZP/Cdb EWTvmmkFFtD4clSMsmqaXPTa3VeaL/saScBPL93tDsjqCddcgW28hsnhzoJ7TM78j2zNcTXZjK8/tNCDnShsAIAA7kBDQRT9s/EAQGA5ggDCKTqedfMsFJRuT83uR3aYBokBdul88MVLd5jwDFwVEO76kTA/ 8zWoD1yrYaf6eLdI0aBcBcBfuwqka8ZL9ka4+Tqgw+yahE2OZ30WdB734uHD5H9oEte0lSOC0hUP7/7CEjTYiNwaP8b6TnivgH9PO4+ARHvL4xbss39PBwoJSqC+lgKfOflnNr4/uxGx+tWJaCijboKt+ AMrjYdUGJpeiyNOG9ikdG/6l01vFKi764eGBmjqZPNJew6QZioBrV5/CRX1PVd7BgrHEp38w7yo6qZrSl4iRcTtqcjwjeY0SnxjDksgH2dtTSKwSREF1r7iAJbPE4pJPSCKSl66QARAQABiQEfBBg BAGAJBQJT9s/eAhsMAAoJEP3jgfPUwdRgwxAH/jgPYYG9xS2xLXDb5FJfcE7S2sa/ZwLAaMKHzRCEx/eoVcoIunpvUY4Nvf/uCa5w4Ym7obBa/xfLiqI/omRhcNjaVx2COskvgs27ly/IzpGAMh qt+BzDVl7ktTa+FRzsSmyppi7vGIXWEZNihfXzyNKI9++guvVvdEfyxwcgq3AoO8ZqgLzvWvBGnO0ZPhXPuTSlcPQ9az+zKmRoCEEKIfIy4iNjG5bxBGocDcQPQGLPFD6TA9KXaPd8MVyGLinONDBeMhS/S3 6T8Q539+93W2EI5N6TU4UOUWoCICzRIUaMOOcf9chHDuhTMeWv4q0F5ydqNV2Eb85wXgrKMjgGG4pCwAgAD
还是不一样。将两个键放入记事本中并搜索“tNCDnS”,之后就是它们发生变化的地方。
谢谢你一直陪着我。我已经对此已经足够了解了,我不想为了一些糟糕的加密而废弃整个代码。
您可能是 BouncyCastle 对术语“密钥环”的不常见使用的受害者。以下是 BouncyCastle 对三个相关术语的用法:
PgpPublicKey:这是 PGP 格式的单个数学密钥的公共部分。它不包含任何子项。
PgpPublicKeyRing:这是一个加密密钥及其子密钥。其他程序通常将此称为 PGP 密钥。
PgpPublicKeyRingBundle:这是任意数量的 PgpPublicKeyRing(如 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;
}
Run Code Online (Sandbox Code Playgroud)
编辑:以下是一个完整的程序,没有外部依赖项。它对我有用,即输出“相同!”。请运行该程序并检查它是否输出“相同!” 或“差异!”。如果它输出“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;
}
}
Run Code Online (Sandbox Code Playgroud)