.NET 2.0 code for encryption of PayPal buttons
public sealed class PayPalEncrypt
{
private static byte[] SignMsg(byte[] msg, X509Certificate2 signerCert)
{
// Place message in a ContentInfo object.
// This is required to build a SignedCms object.
ContentInfo contentInfo = new ContentInfo(msg);
// Instantiate SignedCms object with the ContentInfo above.
// Has default SubjectIdentifierType IssuerAndSerialNumber.
// Has default Detached property value false, so message is
// included in the encoded SignedCms.
SignedCms signedCms = new SignedCms(contentInfo);
// Formulate a CmsSigner object, which has all the needed
// characteristics of the signer.
CmsSigner cmsSigner = new CmsSigner(signerCert);
//cmsSigner.DigestAlgorithm;
// Sign the PKCS #7 message.
signedCms.ComputeSignature(cmsSigner);
//PKCS7_add_signed_attribute(si, NID_pkcs9_contentType, V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data))
//AsnEncodedData aed = new AsnEncodedData(msg);
//cmsSigner.SignedAttributes.Add(aed);
// Encode the PKCS #7 message.
return signedCms.Encode();
}
private static byte[] EncryptMsg(byte[] msg, X509Certificate2 recipientCert, X509Certificate2 senderCert)
{
// Place message in a ContentInfo object.
// This is required to build an EnvelopedCms object.
ContentInfo contentInfo = new ContentInfo(msg);
// Instantiate EnvelopedCms object with the ContentInfo above.
// Has default SubjectIdentifierType IssuerAndSerialNumber.
// Has default ContentEncryptionAlgorithm property value
// RSA_DES_EDE3_CBC.
EnvelopedCms envelopedCms = new EnvelopedCms(contentInfo);
// Formulate a CmsRecipient object that
// represents information about the recipient
// to encrypt the message for.
CmsRecipient recip1 = new CmsRecipient(SubjectIdentifierType.IssuerAndSerialNumber, recipientCert);
// Encrypt the message for the recipient.
envelopedCms.Encrypt(recip1);
envelopedCms.Certificates.Add(senderCert);
// The encoded EnvelopedCms message contains the encrypted
// message and the information about each recipient that
// the message was enveloped for.
//envelopedCms
return envelopedCms.Encode();
}
///
///
///
///
///
///
///
///
///
public static string DecryptAndVerify(String sBase64, String senderCertPath, String recipientKeyPath, String recipientCertPath, ref String sResult)
{
if (sBase64.StartsWith("-----BEGIN PKCS7-----"))
{
sBase64 = sBase64.Substring(21);
sBase64 = sBase64.Substring(0, sBase64.IndexOf("---"));
}
sBase64 = sBase64.Replace("\r\n", "\n");
sBase64 = sBase64.Trim();
X509Certificate2 certRecipient = new X509Certificate2(recipientCertPath);
X509Certificate2 certSender = new X509Certificate2(senderCertPath);
byte[] msg = Convert.FromBase64String(sBase64);
msg = DecryptMsg(msg, certRecipient);
return Encoding.ASCII.GetString(ExtractEnvelopedData(msg)).Replace("\n", "\r\n");
}
private static byte[] ExtractEnvelopedData(byte[] signature)
{
if (signature == null)
throw new ArgumentNullException("signature");
// decode the signature
SignedCms cms = new SignedCms();
cms.Decode(signature);
if (cms.Detached)
throw new InvalidOperationException("Cannot extract enveloped content from a detached signature.");
return cms.ContentInfo.Content;
}
// Verify the encoded SignedCms message and return a Boolean
// value that specifies whether the verification was successful.
private static bool VerifyMsg(byte[] encodedSignedCms, X509Certificate2 sender)
{
// Prepare an object in which to decode and verify.
SignedCms signedCms = new SignedCms();
signedCms.Decode(encodedSignedCms);
// Catch a verification exception if you want to
// advise the message recipient that
// security actions might be appropriate.
try
{
X509Certificate2Collection col = new X509Certificate2Collection(sender);
signedCms.CheckSignature(col, true);
}
catch (System.Security.Cryptography.CryptographicException)
{
return false;
}
return true;
}
private static byte[] DecryptMsg(byte[] encodedEnvelopedCms, X509Certificate2 recipient)
{
// Prepare object in which to decode and decrypt.
EnvelopedCms envelopedCms = new EnvelopedCms();
// Decode the message.
envelopedCms.Decode(encodedEnvelopedCms);
// Display the number of recipients the message is
// enveloped for; it should be 1 for this example.
//DisplayEnvelopedCms(envelopedCms, false);
// Decrypt the message for the single recipient.
// Note that the following call to the Decrypt method
// accomplishes the same result:
// envelopedCms.Decrypt();
X509Certificate2Collection col = new X509Certificate2Collection(recipient);
envelopedCms.Decrypt(col);
return envelopedCms.Encode();
}
///
///
///
///
///
///
///
///
///
public static string SignAndEncryptWithPassword(String sCmdTxt, String senderCertPath, String senderKeyPassword, String recipientCertPath)
{
X509Certificate2 certRecipient = new X509Certificate2(recipientCertPath);
X509Certificate2 certSender = new X509Certificate2(senderCertPath, senderKeyPassword);
return SignAndEncrypt(sCmdTxt, certSender, certRecipient);
}
///
///
///
///
///
///
///
///
///
public static string SignAndEncrypt(String sCmdTxt, String senderCertPath, String senderKeyPath, String recipientCertPath)
{
X509Certificate2 certRecipient = new X509Certificate2(recipientCertPath);
System.Security.Cryptography.RSA r = GetRsa(senderKeyPath);
X509Certificate2 certSender = new X509Certificate2(senderCertPath);
certSender.PrivateKey = r;
return SignAndEncrypt(sCmdTxt, certSender, certRecipient);
}
///
///
///
///
///
///
///
///
public static string SignAndEncrypt(String sCmdTxt, X509Certificate2 certSender, X509Certificate2 certReceipient)
{
byte[] encodedCms = SignMsg(System.Text.Encoding.ASCII.GetBytes(sCmdTxt), certSender);
encodedCms = EncryptMsg(encodedCms, certReceipient, certSender);
string result2 = System.Convert.ToBase64String(encodedCms);
string result = "-----BEGIN PKCS7-----\r\n";
while (result2.Length > 64)
{
result += result2.Substring(0, 64) + "\r\n";
result2 = result2.Substring(64);
}
result += result2 + "\r\n-----END PKCS7-----\r\n";
return result;
}
private static System.Security.Cryptography.RSACryptoServiceProvider GetRsa(String keyPath)
{
System.IO.FileStream fs = System.IO.File.OpenRead(keyPath);
StreamReader sr = new StreamReader(fs);
string t = sr.ReadToEnd();
sr.Close();
if (!t.StartsWith("-----BEGIN RSA PRIVATE KEY-----"))
{
throw new ArgumentException("Not an RSA Private Key");
}
t = t.Substring("-----BEGIN RSA PRIVATE KEY-----".Length);
t = t.Substring(0, t.IndexOf("----"));
t = t.Replace("\r", "").Replace("\n", "");
byte[] byteArray = System.Convert.FromBase64String(t);
System.IO.MemoryStream s = new MemoryStream(byteArray);
BinaryReader binr = new BinaryReader(s);
byte[] MODULUS, E, D, P, Q, DP, DQ, IQ;
// --------- Set up stream to decode the asn.1 encoded RSA private key ------
byte bt = 0;
ushort twobytes = 0;
int elems = 0;
RSAParameters result = new RSAParameters();
try
{
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return null;
twobytes = binr.ReadUInt16();
if (twobytes != 0x0102) //version number
return null;
bt = binr.ReadByte();
if (bt != 0x00)
return null;
//------ all private key components are Integer sequences ----
elems = GetIntegerSize(binr);
MODULUS = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
E = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
D = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
P = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
Q = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DP = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
DQ = binr.ReadBytes(elems);
elems = GetIntegerSize(binr);
IQ = binr.ReadBytes(elems);
result.Modulus = MODULUS;
result.Exponent = E;
result.D = D;
result.P = P;
result.Q = Q;
result.DP = DP;
result.DQ = DQ;
result.InverseQ = IQ;
}
catch (Exception)
{
return null;
}
finally
{
binr.Close();
}
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
RSA.ImportParameters(result);
return RSA;
}
private static int GetIntegerSize(BinaryReader binr)
{
byte bt = 0;
byte lowbyte = 0x00;
byte highbyte = 0x00;
int count = 0;
bt = binr.ReadByte();
if (bt != 0x02) //expect integer
return 0;
bt = binr.ReadByte();
if (bt == 0x81)
count = binr.ReadByte(); // data size in next byte
else
if (bt == 0x82) {
highbyte = binr.ReadByte(); // data size in next 2 bytes
lowbyte = binr.ReadByte();
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
count = BitConverter.ToInt32(modint, 0);
}
else
{
count = bt; // we already have the data size
}
while (binr.PeekChar() == 0x00)
{ //remove high order zeros in data
binr.ReadByte();
count -= 1;
}
return count;
}
}