Discussion:
OpenPGP questions
Holovacs, Jeremy
2013-09-18 14:54:37 UTC
Permalink
I'm having a deuce of a time trying to get OpenPGP to work in-memory (no
files) to encrypt data for a vendor. I've been trying to get the examples
to work with streams instead of files and paths, and not having a whole lot
of luck.

I was wondering if someone could give me some pointers about what I'm doing
wrong. I have a utility class like so:

using System;
using System.IO;
using System.Linq;
using System.Text;
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;

namespace OpenPGP.Utilities
{
public static class OpenPgpUtility
{
public static void ExportKeyPair(
Stream secretOut,
Stream publicOut,
AsymmetricKeyParameter publicKey,
AsymmetricKeyParameter privateKey,
string identity,
char[] passPhrase,
bool armor)
{
if (armor)
{
secretOut = new ArmoredOutputStream(secretOut);
}

var secretKey = new PgpSecretKey(
PgpSignature.DefaultCertification,
PublicKeyAlgorithmTag.RsaGeneral,
publicKey,
privateKey,
DateTime.UtcNow,
identity,
SymmetricKeyAlgorithmTag.Cast5,
passPhrase,
null,
null,
new SecureRandom()
);

secretKey.Encode(secretOut);

if (armor)
{
secretOut.Close();
publicOut = new ArmoredOutputStream(publicOut);
}

var key = secretKey.PublicKey;

key.Encode(publicOut);

if (armor)
{
publicOut.Close();
}
}

public static PgpPublicKey ImportPublicKey(
this Stream publicIn)
{
var pubRings =
new
PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(publicIn)).GetKeyRings().OfType<PgpPublicKeyRing>();
var pubKeys = pubRings.SelectMany(x =>
x.GetPublicKeys().OfType<PgpPublicKey>());
var pubKey = pubKeys.FirstOrDefault();
return pubKey;
}

public static PgpSecretKey ImportSecretKey(
this Stream secretIn)
{
var secRings =
new
PgpSecretKeyRingBundle(PgpUtilities.GetDecoderStream(secretIn)).GetKeyRings().OfType<PgpSecretKeyRing>();
var secKeys = secRings.SelectMany(x =>
x.GetSecretKeys().OfType<PgpSecretKey>());
var secKey = secKeys.FirstOrDefault();
return secKey;
}

public static Stream Streamify(this string theString, Encoding encoding =
null)
{
encoding = encoding ?? Encoding.UTF8;
var stream = new MemoryStream(encoding.GetBytes(theString));
return stream;
}

public static string Stringify(this Stream theStream,
Encoding encoding = null)
{
encoding = encoding ?? Encoding.UTF8;
using (var reader = new StreamReader(theStream, encoding))
{
return reader.ReadToEnd();
}
}

public static byte[] ReadFully(this Stream stream)
{
if (!stream.CanRead) throw new ArgumentException("This is not a readable
stream.");
var buffer = new byte[32768];
using (var ms = new MemoryStream())
{
while (true)
{
var read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
}

internal static Stream PgpCompress(this Stream toCompress,
CompressionAlgorithmTag algorithm = CompressionAlgorithmTag.Zip)
{
var compressor = new PgpCompressedDataGenerator(algorithm);
var data = toCompress.ReadFully();
var bytesOut = new MemoryStream();

var literalData = new PgpLiteralDataGenerator();
using (var literalStream = literalData.Open(bytesOut,'b',"STREAM",
DateTime.UtcNow, data))
using (var compressedStream = compressor.Open(literalStream))
{
compressedStream.Write(data, 0, data.Length);
}

bytesOut.Position = 0;
return bytesOut;
}

public static void PgpEncrypt(
this Stream toEncrypt,
Stream outStream,
PgpPublicKey encryptionKey,
bool armor = true,
bool verify = false,
CompressionAlgorithmTag compressionAlgorithm = CompressionAlgorithmTag.Zip)
{
var encryptor = new
PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, verify, new
SecureRandom());
encryptor.AddMethod(encryptionKey);

if (armor)
{
outStream = new ArmoredOutputStream(outStream);
}

var compressedData =
toEncrypt.PgpCompress(compressionAlgorithm).ReadFully();
outStream = encryptor.Open(outStream, compressedData.Length);
outStream.Write(compressedData, 0, compressedData.Length);
}

}
}

I run my test like so:

private static void EncryptMessage()
{
var pubKey = @"-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.21 (MingW32)
<stuff>
-----END PGP PUBLIC KEY BLOCK-----";

var clearText = @"My text to encrypt";
using (var stream = pubKey.Streamify())
{
var key = stream.ImportPublicKey();
using (var clearStream = clearText.Streamify())
using (var cryptoStream = new MemoryStream())
{
clearStream.PgpEncrypt(cryptoStream, key);
cryptoStream.Position = 0;
var cryptoString = cryptoStream.Stringify();
Console.WriteLine(cryptoString);
Console.WriteLine("Press any key to continue.");
}
}
Console.ReadKey();
}

I will get an output, but it does not seem complete. It looks like this:

-----BEGIN PGP MESSAGE-----
Version: BCPG C# v1.7.5008.27658

hQEMA+TTNfaRZvkeAQgAkvLMZn43cumcEoHmrGZGI6atPSIK6Yk63ELHHprwgcKL
AvlkrfoNMGjzT1sQZaS2gEchJE6tEKBuxbo0eyDvnC6bug8V7Pumn5jqMm8xG8sj
f7jREo6j6DRwFiKPYPLlwo4aA7ou9gkjj12YNR/doXx44Y3psXuGGdjVkFqVkz7H
yziV0nLS1zpbXm8g7HMQIaqyDj9datPtsE0eLyN0+HKuoxL5K6ffgVp9fMeYlh5R
XCsOoPWCt41xtzt9gRd/pQP0XjD5p0I1+CbTsdEDmdimEWSH1EhNp8QSzl0yJPTq
Rfelefd5YuvyrIfzvLKCWTdstsGimWP0zS5a8cKdh8nBUKL22uGb9HbbU6kT6Nm1
j3gCR38KNHBObfTjCVHihOlAASzhNATWkjxHYBMa6YQ6S2t4lxaWacU15Xy2A+x4
nFGfofP0lN24B6JsvI4/AOU/oO7961w+r4GmyJet1Ncy9PlqIEPl6s6ot0zTsY4W
cQPQtYFxx+VVNydSi44wc5khPTUQ/IFWy+R1ZLTbgld98oDNxZEFr2TqXtlj/kSk
kDzvxnk+Yzi/5reaZzCwNjrrqSMjmrIkGHO4W0/6+2w28RlIVVuT2wRx2u+55key
D9JeAAlCOwCs2I+zDmUdb2nz3iyspsMZYXDv6ksrXYlLtTgbR3y8/dBmOcsOxtZV
UuP//v2dU7eU8L+NIrpUytnLvUfxpSJ8d3KNgaQ1Pqk4l+oLhcgIgR18ami7Vm1/
gPBfOiFer4EEq1avSioQmleCj987namaDKPTyUtw9Ved9BflIG49LuxrS3Xp2tdF
y4jhXWHIdAEMXLi6IDkOXyHSZZdR/cNELBZmkv4WtbyelJCTNa76Vp8jO1Y3VNxy
sfjRHm1jT42tgFaywouzvcWyQ9DfM5b3qMjgFaRxvNmTnCJFxt7q+ybaZHwfttu0
jOg9IE1iTsA7K5GXOpO6RysA47AA6/NZkqmN3Lid8+RZHo1h4wH+L8nkdRm5PL3f
/VmR0jUUUXB6s8bJkjHF3YrAwkkMpAr2tr4wSjAz9HNi
Press any key to continue.

Note the lack of a footer or ending characters.

What am I doing wrong?
--
*Jeremy Holovacs*
--
This message may contain confidential and/or privileged information. If you
are not the intended recipient or authorized to receive this for the
intended recipient, you must not use, copy, disclose or take any action
based on this message or any information herein. If you have received this
message in error, please advise the sender immediately by sending a reply
e-mail and delete this message. Thank you for your cooperation.
Loading...