Click here to Skip to main content
15,886,110 members
Articles / Programming Languages / C#

SharpPrivacy - OpenPGP for C#

Rate me:
Please Sign up or sign in to vote.
4.92/5 (86 votes)
7 Jun 200314 min read 353.5K   8.4K   227  
SharpPrivacy is an OpenPGP implementation in C#. It can be used to encrypt and sign data, created OpenPGP compatible keys, and a lot more. This article explains how to use the library in your own .NET application or webpage to encrypt, sign, decrypt or verify OpenPGP messages.
//
// This file is part of the source code distribution of SharpPrivacy.
// SharpPrivacy is an Open Source OpenPGP implementation and can be 
// found at http://www.sharpprivacy.net
// It is released under Gnu General Public License and can be used 
// and modified as long as the result is released under GPL too. 
// For a copy of the GPL, please go to www.gnu.org/copyleft/gpl.html 
//
// TransportablePublicKey.cs: 
// 	Class for handling public keys in their transportable format.
//
// Author:
//	Daniel Fabian (df@sharpprivacy.net)
//
//
// Version: 0.1.0 (initial release)
//
// Changelog:
//	- 23.02.2003: Created this file.
//	- 01.06.2003: Added this header for the first beta release.
//
// (C) 2003, Daniel Fabian
//
using System;
using System.Windows.Forms;
using SharpPrivacy.Cipher;
using System.Collections;

namespace SharpPrivacy.OpenPGP.Messages {
	
	/// <summary>
	/// Transportable Public Key is an OpenPGP message as specified in
	/// RFC2440. It contains a user's public key, its subkeys, any user
	/// ids as well as certifications (signatures).
	/// </summary>
	/// <remarks>
	/// Transportable Public Key is an OpenPGP message as specified in
	/// RFC2440. It contains a user's public key, its subkeys, any user
	/// ids as well as certifications (signatures).
	/// </remarks>
	public class TransportablePublicKey {
		private PublicKeyPacket pkpPrimaryKey;
		private ArrayList alRevocationSignatures;
		private ArrayList alCertifications;
		private ArrayList alSubkeys;
		private string strPrimaryUserID;
		
		/// <summary>
		/// Creates a new Transportable secret key with the
		/// parameters of the base64 encoded key given as
		/// argument.
		/// </summary>
		/// <param name="strBase64">A transportable public key
		/// encoded in base64.</param>
		/// <remarks>No remarks</remarks>
		public TransportablePublicKey(string strBase64) {
			alRevocationSignatures = new ArrayList();
			alCertifications = new ArrayList();
			alSubkeys = new ArrayList();
			strPrimaryUserID = "";
			this.Parse(strBase64);
		}

		/// <summary>
		/// Creates a new Transportable public key. No special
		/// preferences are choses.
		/// </summary>
		/// <remarks>No remarks</remarks>
		public TransportablePublicKey() {
			alRevocationSignatures = new ArrayList();
			alCertifications = new ArrayList();
			alSubkeys = new ArrayList();
			strPrimaryUserID = "";
		}
		
		/// <summary>
		/// Readonly. Returns the primary user id of the transportable
		/// public key.
		/// </summary>
		/// <remarks>No remarks</remarks>
		/// <value>
		/// Readonly. Returns the primary user id of the transportable
		/// public key.
		/// </value>
		public string PrimaryUserID {
			get {
				if (strPrimaryUserID.Length == 0)
					strPrimaryUserID = FindPrimaryUserID();
				
				return strPrimaryUserID;
			}
		}
		
		public DateTime KeyExpirationTime {
			get {
				DateTime dtExpiration = this.FindExpirationDate();
				return new DateTime(this.PrimaryKey.TimeCreated.Ticks + (dtExpiration.Ticks - new DateTime(1970, 1, 1).Ticks));
			}
		}
		/// <summary>
		/// Gets or sets the primary key of the transportable public key.
		/// </summary>
		/// <remarks>No remarks</remarks>
		/// <value>
		/// Gets or sets the primary key of the transportable public key.
		/// </value>
		public PublicKeyPacket PrimaryKey {
			get {
				return pkpPrimaryKey;
			}
			set {
				pkpPrimaryKey = value;
			}
		}
		
		/// <summary>
		/// An arraylist containing revocation signatures for the key.
		/// </summary>
		/// <remarks>No remarks</remarks>
		/// <value>
		/// An arraylist containing revocation signatures for the key.
		/// </value>
		public ArrayList RevocationSignatures {
			get {
				return alRevocationSignatures;
			}
			set {
				alRevocationSignatures = value;
			}
		}
		
		/// <summary>
		/// An Arraylist containing certifications (trust signatures)
		/// for the key.
		/// </summary>
		/// <remarks>No remarks</remarks>
		/// <value>
		/// An Arraylist containing certifications (trust signatures)
		/// for the key.
		/// </value>
		public ArrayList Certifications {
			get {
				return alCertifications;
			}
			set {
				alCertifications = value;
			}
		}
		
		/// <summary>
		/// An arraylist containing all the subkeys belonging to the
		/// key.
		/// </summary>
		/// <remarks>No remarks</remarks>
		/// <value>
		/// An arraylist containing all the subkeys belonging to the
		/// key.
		/// </value>
		public ArrayList SubKeys {
			get {
				return alSubkeys;
			}
			set {
				alSubkeys = value;
			}
		}
		
		/// <summary>
		/// Returns a string representation of the transportable public key.
		/// </summary>
		/// <remarks>No remarks</remarks>
		/// <returns>Returns a string representation of the transportable
		/// public key.</returns>
		public override string ToString() {
			string strReturn = "";
			
			strReturn += "Abstract:\r\n";
			strReturn += "Number of Certificates: " + this.Certifications.Count + "\r\n";
			
			
			strReturn += "\r\n\r\n\r\nPublic Key Packet: \r\n";
			strReturn += this.PrimaryKey.ToString() + "\r\n\r\n";
			
			IEnumerator ieLoop = this.Certifications.GetEnumerator();
			while (ieLoop.MoveNext()) {
				if (ieLoop.Current is CertifiedUserID) {
					CertifiedUserID cuiUserID = (CertifiedUserID)ieLoop.Current;
					strReturn += cuiUserID.ToString();
				}
			}
			
			return strReturn;
		}
		
		/// <summary>
		/// Generates the transportable public key out of the properties
		/// in this.
		/// </summary>
		/// <remarks>No remarks</remarks>
		/// <returns>Returns a byte array containing the openpgp encoded
		/// representation of the transportable public key.</returns>
		public byte[] Generate() {
			byte[] bPrimaryKey = this.PrimaryKey.Generate();
			
			//Revocation signatures
			int iLength = 0;
			IEnumerator ieRevocations = this.RevocationSignatures.GetEnumerator();
			while (ieRevocations.MoveNext()) {
				if (ieRevocations.Current is SignaturePacket) {
					iLength += ((SignaturePacket)ieRevocations.Current).Generate().Length;
				}
			}
			byte[] bRevocations = new byte[iLength];
			ieRevocations = this.RevocationSignatures.GetEnumerator();
			int iPosition = 0;
			while (ieRevocations.MoveNext()) {
				if (ieRevocations.Current is SignaturePacket) {
					byte[] bRev = ((SignaturePacket)ieRevocations.Current).Generate();
					Array.Copy(bRev, 0, bRevocations, iPosition, bRev.Length);
					iPosition += bRev.Length;
				}
			}
			
			//Certificates
			iLength = 0;
			IEnumerator ieCertificates = this.Certifications.GetEnumerator();
			while (ieCertificates.MoveNext()) {
				if (ieCertificates.Current is CertifiedUserID) {
					CertifiedUserID cuiID = (CertifiedUserID)ieCertificates.Current;
					iLength += cuiID.Generate().Length;
				}
			}
			byte[] bCertificates = new byte[iLength];
			iPosition = 0;
			ieCertificates = this.Certifications.GetEnumerator();
			while (ieCertificates.MoveNext()) {
				if (ieCertificates.Current is CertifiedUserID) {
					CertifiedUserID cuiID = (CertifiedUserID)ieCertificates.Current;
					byte[] bCert = cuiID.Generate();
					Array.Copy(bCert, 0, bCertificates, iPosition, bCert.Length);
					iPosition += bCert.Length;
				}
			}
			
			//SubKeys
			iLength = 0;
			IEnumerator ieSubkeys = this.SubKeys.GetEnumerator();
			while (ieSubkeys.MoveNext()) {
				if (ieSubkeys.Current is CertifiedPublicSubkey) {
					CertifiedPublicSubkey cpsKey = (CertifiedPublicSubkey)ieSubkeys.Current;
					iLength += cpsKey.Generate().Length;
				}
			}
			byte[] bSubkeys = new byte[iLength];
			iPosition = 0;
			ieSubkeys = this.SubKeys.GetEnumerator();
			while (ieSubkeys.MoveNext()) {
				if (ieSubkeys.Current is CertifiedPublicSubkey) {
					CertifiedPublicSubkey cpsKey = (CertifiedPublicSubkey)ieSubkeys.Current;
					byte[] bKey = cpsKey.Generate();
					Array.Copy(bKey, 0, bSubkeys, iPosition, bKey.Length);
					iPosition += bKey.Length;
				}
			}
			
			byte[] bData = new byte[bPrimaryKey.Length + bRevocations.Length +
									bCertificates.Length + bSubkeys.Length];
			iPosition = 0;
			Array.Copy(bPrimaryKey, bData, bPrimaryKey.Length);
			iPosition = bPrimaryKey.Length;
			Array.Copy(bRevocations, 0, bData, iPosition, bRevocations.Length);
			iPosition += bRevocations.Length;
			Array.Copy(bCertificates, 0, bData, iPosition, bCertificates.Length);
			iPosition += bCertificates.Length;
			Array.Copy(bSubkeys, 0, bData, iPosition, bSubkeys.Length);
			
			return bData;
			
		}
		
		/// <summary>
		/// Finds a subkey (or the primary key) with the given keyid
		/// and returns it. Returns null if the the fitting key has
		/// not been found.
		/// </summary>
		/// <remarks>If the public key has been revoked, it is ignored
		/// and NOT found by this function!!!</remarks>
		/// <param name="lKeyID">The keyid to be sought in the transportable
		/// public key.</param>
		/// <returns>The subkey (or the primary key) with the given keyid.
		/// Null if the the fitting key has not been found.</returns>
		public PublicKeyPacket FindKey(ulong lKeyID) {
			
			if (pkpPrimaryKey.KeyID == lKeyID)
				return pkpPrimaryKey;
			
			IEnumerator ieSubkeys = alSubkeys.GetEnumerator();
			while (ieSubkeys.MoveNext()) {
				CertifiedPublicSubkey cpsKey = (CertifiedPublicSubkey)ieSubkeys.Current;
				
				// The subkey has been revoced
				if (cpsKey.RevocationSignature != null) 
					continue;
				
				PublicKeyPacket pkpKey = cpsKey.Subkey;
				if (pkpKey.KeyID == lKeyID)
					return pkpKey;
			}
			
			return null;
		}
		
		/// <summary>
		/// Finds a subkey (or the primary key) that fits to the given 
		/// requirements (meaning it must be supposed to be used for 
		/// the given action, which can be either signing or encryption).
		/// If more than just one keys fullfill the requirements, the one
		/// with the newer creationdate is used.
		/// </summary>
		/// <remarks>No remarks</remarks>
		/// <param name="aaAction">The action (signing or encrypting) for
		/// which the key should be used</param>
		/// <returns>Returns a public key packet fullfilling the given
		/// requirements (the action) or null, if it did not find such
		/// a key.</returns>
		public PublicKeyPacket FindKey(AsymActions aaAction) {
			DateTime dtCandidateTime = DateTime.Now;
			PublicKeyPacket pkpCandidate = new PublicKeyPacket();
			bool bFound = false;
			
			// First check the primary Key
			if (aaAction == AsymActions.Encrypt) {
				if (pkpPrimaryKey.Algorithm == AsymAlgorithms.ElGama_Encrypt_Sign ||
				    pkpPrimaryKey.Algorithm == AsymAlgorithms.ElGamal_Encrypt_Only ||
				    pkpPrimaryKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Only ||
				    pkpPrimaryKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Sign) {
					
					dtCandidateTime = pkpPrimaryKey.TimeCreated;
					bFound = true;
					pkpCandidate = pkpPrimaryKey;
				}
			} else if (aaAction == AsymActions.Sign) {
				if (pkpPrimaryKey.Algorithm == AsymAlgorithms.ElGama_Encrypt_Sign ||
				    pkpPrimaryKey.Algorithm == AsymAlgorithms.DSA ||
				    pkpPrimaryKey.Algorithm == AsymAlgorithms.RSA_Sign_Only ||
				    pkpPrimaryKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Sign) {
					
					dtCandidateTime = pkpPrimaryKey.TimeCreated;
					bFound = true;
					pkpCandidate = pkpPrimaryKey;
				}
			}
			
			// Now check the subkeys
			IEnumerator ieSubkeys = alSubkeys.GetEnumerator();
			while (ieSubkeys.MoveNext()) {
				CertifiedPublicSubkey cpsKey = (CertifiedPublicSubkey)ieSubkeys.Current;
				
				// The subkey has been revoced
				if (cpsKey.RevocationSignature != null) 
					continue;
				
				PublicKeyPacket pkpKey = cpsKey.Subkey;
				if (aaAction == AsymActions.Encrypt) {
					
					if (pkpKey.Algorithm == AsymAlgorithms.ElGama_Encrypt_Sign ||
					    pkpKey.Algorithm == AsymAlgorithms.ElGamal_Encrypt_Only ||
					    pkpKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Only ||
					    pkpKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Sign) {
						
						if ((bFound && dtCandidateTime < pkpKey.TimeCreated) || (!bFound)) {
							dtCandidateTime = pkpKey.TimeCreated;
							bFound = true;
							pkpCandidate = pkpKey;
						}
					}
				} else if (aaAction == AsymActions.Sign) {
					if (pkpKey.Algorithm == AsymAlgorithms.ElGama_Encrypt_Sign ||
					    pkpKey.Algorithm == AsymAlgorithms.DSA ||
					    pkpKey.Algorithm == AsymAlgorithms.RSA_Sign_Only ||
					    pkpKey.Algorithm == AsymAlgorithms.RSA_Encrypt_Sign) {
						
						if ((bFound && dtCandidateTime < pkpKey.TimeCreated) || (!bFound)) {
							dtCandidateTime = pkpKey.TimeCreated;
							bFound = true;
							pkpCandidate = pkpKey;
						}
					}
				}
				
			}
			
			if (bFound)
				return pkpCandidate;
			
			return null;
		}
		
		/// <summary>
		/// Returns true if the given object is the "this" key.
		/// </summary>
		/// <remarks>
		/// The keys are compared by there fingerprint. If the fingerprint
		/// is the same, the keys are said to be the same.
		/// </remarks>
		/// <param name="o">An object that shall be compared against 
		/// this.</param>
		/// <returns>True if the giben object o is the same as the
		/// "this" key.</returns>
		public override bool Equals(object o) {
			if (o is TransportablePublicKey) {
				TransportablePublicKey tpkKey = (TransportablePublicKey)o;
				return (tpkKey.PrimaryKey.Fingerprint == this.PrimaryKey.Fingerprint);
			}
			return false;
		}
		
		public override int GetHashCode() {
			return (int)(this.PrimaryKey.KeyID & 0xFFFFFFFF);
		}
		
		
		/// <summary>
		/// Parses the radix64 encoded representation of a transportable public
		/// key given as an argument to populate the parameters of this.
		/// </summary>
		/// <remarks>No remarks</remarks>
		/// <param name="strRadix64">Radix64 representation of an transportable
		/// public key</param>
		/// <exception cref="System.ArgumentException">Throws an 
		/// ArgumentException if the radix64 string given as a parameter is
		/// not an transportable public key.</exception>
		public void Parse(string strRadix64) {
			Packet[] pPackets = Packet.ParsePackets(strRadix64);
			
			int nCurrentPacket = 0;
			int nUserIDCounter = 0;
			
			try {
				// First we expect a PublicKeyPacket
				if (!(pPackets[0] is PublicKeyPacket)) {
					throw(new ArgumentException("The given packet is not in the required transportable public key format!"));
				}
				this.PrimaryKey = (PublicKeyPacket)pPackets[nCurrentPacket++];
				
				// Next we expect zero or more revocation signatures
				while ((nCurrentPacket < pPackets.Length) && (pPackets[nCurrentPacket] is SignaturePacket)) {
					SignaturePacket spRevocation = (SignaturePacket)pPackets[nCurrentPacket++];
					if (spRevocation.SignatureType != SignatureTypes.KeyRevocationSignature) {
						throw(new ArgumentException("The given packet is not in the required transportable public key format!"));
					}
					this.RevocationSignatures.Add(spRevocation);
				}
				
				// Next in queue must be one or more UserID Packets
				while ((nCurrentPacket < pPackets.Length) && (pPackets[nCurrentPacket] is UserIDPacket)) {
					nUserIDCounter++;
					CertifiedUserID cuiUserID = new CertifiedUserID();
					UserIDPacket uipUserID = (UserIDPacket)pPackets[nCurrentPacket++];
					cuiUserID.UserID = uipUserID;
					
					// For every UserIDPacket we expect zero or more Signatures (Certificates)
					while ((nCurrentPacket < pPackets.Length) && (pPackets[nCurrentPacket] is SignaturePacket)) {
						SignaturePacket spCertificate = (SignaturePacket)pPackets[nCurrentPacket++];
						if ((spCertificate.SignatureType != SignatureTypes.UserIDSignature) &&
						    (spCertificate.SignatureType != SignatureTypes.UserIDSignature_CasualVerification) &&
						    (spCertificate.SignatureType != SignatureTypes.UserIDSignature_NoVerification) &&
						    (spCertificate.SignatureType != SignatureTypes.UserIDSignature_PositivVerification)) {
							throw(new ArgumentException("The given packet is not in the required transportable public key format!"));
						}
						cuiUserID.Certificates.Add(spCertificate);
					}
					this.Certifications.Add(cuiUserID);
				}
				
				// There was no UserIDPacket. This is fatal!!!
				if (nUserIDCounter == 0) {
					throw(new ArgumentException("The given packet is not in the required transportable public key format!"));
				}
				
				// Finally we have zero or more subkeys
				while ((nCurrentPacket < pPackets.Length) && (pPackets[nCurrentPacket] is PublicKeyPacket)) {
					PublicKeyPacket pkpSubKey = (PublicKeyPacket)pPackets[nCurrentPacket++];
					CertifiedPublicSubkey cpsSubKey = new CertifiedPublicSubkey();
					cpsSubKey.Subkey = pkpSubKey;
					
					if ((nCurrentPacket < pPackets.Length) && (pPackets[nCurrentPacket] is SignaturePacket)) {
						SignaturePacket spKeySignature = (SignaturePacket)pPackets[nCurrentPacket++];
						if (spKeySignature.SignatureType == SignatureTypes.SubkeyBindingSignature) {
							cpsSubKey.KeyBindingSignature = spKeySignature;
						} else if (spKeySignature.SignatureType == SignatureTypes.SubkeyRevocationSignature) {
							cpsSubKey.RevocationSignature = spKeySignature;
						}
					} else {
						throw(new ArgumentException("The given packet is not in the required transportable public key format!"));
					}
					if (nCurrentPacket < pPackets.Length) {
						if (pPackets[nCurrentPacket] is SignaturePacket) {
							SignaturePacket spSubkeyRev = (SignaturePacket)pPackets[nCurrentPacket++];
							cpsSubKey.RevocationSignature = spSubkeyRev;
						}
					}
					this.SubKeys.Add(cpsSubKey);
				}
			} catch (System.IndexOutOfRangeException) {
				if (nUserIDCounter == 0) {
					throw(new ArgumentException("The given packet is not in the required transportable public key format!"));
				}
			}
		}
		
		private DateTime FindExpirationDate() {
			IEnumerator ieCertificates = this.alCertifications.GetEnumerator();
			while (ieCertificates.MoveNext()) {
				if (!(ieCertificates.Current is CertifiedUserID))
					continue;
				
				CertifiedUserID cuiID = (CertifiedUserID)ieCertificates.Current;
				IEnumerator ieSignatures = cuiID.Certificates.GetEnumerator();
				while (ieSignatures.MoveNext()) {
					if (!(ieSignatures.Current is SignaturePacket))
						continue;
					
					SignaturePacket spCertificate = (SignaturePacket)ieSignatures.Current;
					
					// look only at selfsignatures
					if (spCertificate.KeyID != this.PrimaryKey.KeyID)
						continue;
					
					for (int i=0; i<spCertificate.HashedSubPackets.Length; i++) {
						if (spCertificate.HashedSubPackets[i].Type == SignatureSubPacketTypes.KeyExpirationTime) {
							return spCertificate.HashedSubPackets[i].KeyExpirationTime;
						}
					}
				}
			}
			
			throw new Exception("never");
			
		}
		
		public SymAlgorithms[] FindPreferedAlgorithms() {
			IEnumerator ieCertificates = this.alCertifications.GetEnumerator();
			while (ieCertificates.MoveNext()) {
				if (!(ieCertificates.Current is CertifiedUserID))
					continue;
				
				CertifiedUserID cuiID = (CertifiedUserID)ieCertificates.Current;
				IEnumerator ieSignatures = cuiID.Certificates.GetEnumerator();
				while (ieSignatures.MoveNext()) {
					if (!(ieSignatures.Current is SignaturePacket))
						continue;
					
					SignaturePacket spCertificate = (SignaturePacket)ieSignatures.Current;
					
					// look only at selfsignatures
					if (spCertificate.KeyID != this.PrimaryKey.KeyID)
						continue;
					
					try {
						SymAlgorithms[] saReturn = spCertificate.FindPreferedSymAlgorithms();
						return saReturn;
					} catch (Exception) {}
					
				}
			}
			
			throw new Exception("none found!");
			
		}
		
		private string FindPrimaryUserID() {
			string strReturn = "";
			int nUserIDCounter = 0;
			IEnumerator ieCertificates = this.alCertifications.GetEnumerator();
			while (ieCertificates.MoveNext()) {
				if (!(ieCertificates.Current is CertifiedUserID))
					continue;
				
				nUserIDCounter++;
				CertifiedUserID cuiID = (CertifiedUserID)ieCertificates.Current;
				IEnumerator ieSignatures = cuiID.Certificates.GetEnumerator();
				while (ieSignatures.MoveNext()) {
					if (!(ieSignatures.Current is SignaturePacket))
						continue;
					
					SignaturePacket spCertificate = (SignaturePacket)ieSignatures.Current;
					
					// look only at selfsignatures
					if (spCertificate.KeyID != this.PrimaryKey.KeyID)
						continue;
					
					if (nUserIDCounter == 1) {
						strReturn = cuiID.UserID.UserID;
					}
					for (int i=0; i<spCertificate.UnhashedSubPackets.Length; i++) {
						if ((spCertificate.UnhashedSubPackets[i].Type == SignatureSubPacketTypes.PrimaryUserID)  && (spCertificate.UnhashedSubPackets[i].PrimaryUserID)) {
							strReturn = cuiID.UserID.UserID;
						}
					}
					for (int i=0; i<spCertificate.HashedSubPackets.Length; i++) {
						if ((spCertificate.HashedSubPackets[i].Type == SignatureSubPacketTypes.PrimaryUserID)  && (spCertificate.HashedSubPackets[i].PrimaryUserID)) {
							strReturn = cuiID.UserID.UserID;
						}
					}
				}
			}
			
			return strReturn;
		}
		
		public static TransportablePublicKey[] SplitKeys(string strRadix64) {
			ArrayList alKeys = new ArrayList();
			Packet[] pPackets = Packet.ParsePackets(strRadix64);
			
			byte[] bOneKey = new byte[0];
			for (int i=0; i<pPackets.Length; i++) {
				if (pPackets[i] is PublicKeyPacket) {
					PublicKeyPacket pkpKey = (PublicKeyPacket)pPackets[i];
					if ((pkpKey.Content == ContentTypes.PublicKey) && (bOneKey.Length > 10)) {
						TransportablePublicKey tpkKey = new TransportablePublicKey(Radix64.Encode(bOneKey, true));
						alKeys.Add(tpkKey);
						bOneKey = new byte[0];
					}
				}
				byte[] bPacket = pPackets[i].Generate();
				byte[] bTmpKey = new byte[bOneKey.Length];
				bOneKey.CopyTo(bTmpKey, 0);
				bOneKey = new byte[bOneKey.Length + bPacket.Length];
				Array.Copy(bTmpKey, 0, bOneKey, 0, bTmpKey.Length);
				Array.Copy(bPacket, 0, bOneKey, bTmpKey.Length, bPacket.Length);
			}
			
			if (bOneKey.Length > 10) {
				TransportablePublicKey tpkKey = new TransportablePublicKey(Radix64.Encode(bOneKey, true));
				alKeys.Add(tpkKey);
			}
			
			TransportablePublicKey[] tpkKeys = new TransportablePublicKey[alKeys.Count];
			int iCount = 0;
			IEnumerator ieKeys = alKeys.GetEnumerator();
			while (ieKeys.MoveNext()) {
				if (!(ieKeys.Current is TransportablePublicKey))
					continue;
				
				tpkKeys[iCount++] = (TransportablePublicKey)ieKeys.Current;
				
			}
			
			return tpkKeys;
		}
		
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Austria Austria
My name is Daniel and I am from Austria.
When I was in High School, all I wanted to do was programming. After finishing High School, I joined a company for which I wrote a project management utility in Visual Basic 6. It was then that I realised that programming all day long was nothing I wanted to do for the rest of my life.

I quit the job and started to study computer and media security at polytechnical university in Hagenberg/Austria.

As of now, I'm still studying. I still like to program, as long as I can do something else too. Recently I switched my favorite programming language to c#. Together with a friend from university, we started a project where we implement OpenPGP (RFC2440) in c#.

Comments and Discussions