/// <summary> /// Parses a single packet out of the given binary /// data. Even if there are more than one packets in the byte /// array, only the first packet is returned. /// </summary> /// <param name="bBinaryData">A byte array containing a set /// of OpenPGP packets</param> /// <returns>Returns an single OpenPGP packets</returns> /// <remarks>No remarks</remarks> public virtual Packet ParsePacket(byte[] bBinaryData) { Packet pReturnPacket = new Packet(); if ((bBinaryData[0] & 0xC0) == 0xC0) { pfFormat = PacketFormats.New; } else if ((bBinaryData[0] & 0xC0) == 0x80) { pfFormat = PacketFormats.Old; } else { throw(new ArgumentException("This is not a valid OpenPGP Packet")); } if (pfFormat == PacketFormats.New) { int iBinaryDataPos = 1; ctContent = (ContentTypes)(bBinaryData[0] & 0x3F); lLength = bBinaryData[1]; bBody = new byte[0]; int iHeaderLength = 1; //partial body lengths while ((lLength > 223) && (lLength < 255)) { iBinaryDataPos += 1; iHeaderLength++; int lPartialBody = 1 << ((int)(lLength & 0x1F)); int lOldLength = 0; if (bBody.Length > 0) { byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lPartialBody]; bOldBody.CopyTo(bBody, 0); lOldLength = bBody.Length; } else { bBody = new byte[lPartialBody]; } Array.Copy(bBinaryData, iBinaryDataPos, bBody, bBody.Length - lPartialBody, lPartialBody); lLength = bBinaryData[iBinaryDataPos + lPartialBody]; iBinaryDataPos += lPartialBody; } //partial bodies must end with a normal header! if (lLength < 192) { iHeaderLength++; bHeader = new byte[iHeaderLength]; if (bBody.Length == 0) { Array.Copy(bBinaryData, 0, bHeader, 0, 2); iBinaryDataPos = 1; } byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lLength]; bOldBody.CopyTo(bBody, 0); Array.Copy(bBinaryData, iBinaryDataPos + 1, bBody, bBody.Length - (int)lLength, (int)lLength); } else if ((lLength > 191) && (lLength < 224)) { iHeaderLength += 2; bHeader = new byte[iHeaderLength]; if (bBody.Length == 0) { Array.Copy(bBinaryData, 0, bHeader, 0, 3); iBinaryDataPos = 1; } lLength = ((bBinaryData[iBinaryDataPos++] - 192) << 8) + bBinaryData[iBinaryDataPos++] + 192; byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lLength]; bOldBody.CopyTo(bBody, 0); Array.Copy(bBinaryData, iBinaryDataPos, bBody, bBody.Length - (int)lLength, (int)lLength); } else if (lLength == 255) { iHeaderLength += 5; bHeader = new byte[iHeaderLength]; if (bBody.Length == 0) { Array.Copy(bBinaryData, 0, bHeader, 0, 6); iBinaryDataPos = 1; } lLength = (bBinaryData[iBinaryDataPos++] << 24) ^ (bBinaryData[iBinaryDataPos++] << 16) ^ (bBinaryData[iBinaryDataPos++] << 8) ^ bBinaryData[iBinaryDataPos++]; byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lLength]; bOldBody.CopyTo(bBody, 0); Array.Copy(bBinaryData, iBinaryDataPos, bBody, bBody.Length - (int)lLength, (int)lLength); } } else { ctContent = (ContentTypes)((bBinaryData[0] & 0x3C) >> 2); switch (bBinaryData[0] & 0x03) { case 0: lLength = bBinaryData[1]; bHeader = new byte[2]; break; case 1: lLength = (bBinaryData[1] << 8) ^ (bBinaryData[2]); bHeader = new byte[3]; break; case 2: lLength = (bBinaryData[1] << 16) ^ (bBinaryData[2] << 8) ^ (bBinaryData[3]); bHeader = new byte[4]; break; case 3: throw new System.NotSupportedException("Packets of indetermined length are not supported due to security considerations!"); default: throw new System.ApplicationException("This is not a valid Packet!"); } bBody = new byte[lLength]; Array.Copy(bBinaryData, 0, bHeader, 0, bHeader.Length); Array.Copy(bBinaryData, bHeader.Length, bBody, 0, (int)lLength); } this.bIsUpdated = false; switch (ctContent) { case ContentTypes.AsymSessionKey: pReturnPacket = new AsymSessionKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Compressed: pReturnPacket = new CompressedDataPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.LiteralData: pReturnPacket = new LiteralDataPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Marker: pReturnPacket = new Packet(this); //We can savly ignore Marker packets! //MessageBox.Show("This is a marker packet. It is not yet supported."); break; case ContentTypes.OnePassSignature: pReturnPacket = new OnePassSignaturePacket(this); //System.Windows.Forms.MessageBox.Show("This is a One Pass Signature Packet. It is not yet supported"); break; //Content is Public Key Packet case ContentTypes.PublicKey: pReturnPacket = new PublicKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; //Content is Public Subkey Packet. Same format as Public Key Packet case ContentTypes.PublicSubkey: pReturnPacket = new PublicKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SecretKey: pReturnPacket = new SecretKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SecretSubkey: pReturnPacket = new SecretKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Signature: pReturnPacket = new SignaturePacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SymEncrypted: pReturnPacket = new SymmetricallyEncryptedDataPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SymSessionKey: pReturnPacket = new SymSessionKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Trust: pReturnPacket = new Packet(this); //throw new Exception("This is a Trust Packet. It is not yet supported"); break; case ContentTypes.UserID: pReturnPacket = new UserIDPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; default: pReturnPacket = new Packet(this); //throw new Exception("Sorry, but this is a packet I don't know about!"); break; } pReturnPacket.bIsUpdated = false; return(pReturnPacket); }
/// <summary> /// Generate a key pair /// </summary> /// <param name="iKeySize">Encription key size</param> /// <param name="strPassphrase">passhrase for the key pair</param> /// <param name="userID">primary user id</param> /// <param name="email">user email</param> /// <param name="notation">xml encoded user info</param> /// <param name="expirationTime">expiration date of the primary key (new DateTime(0) == never)</param> /// <param name="keyType">1: RSA/DSA 0:Elgamal/DSA(DEFAULT)</param> /// <param name="isRevocableKey">revocable?</param> /// <param name="isRevocableSubkey">revocable subkey?</param> public void GenerateKey(int iKeySize, string strPassphrase, string userID, string email, string notation, DateTime expirationTime, int keyType, bool isRevocableKey, bool isRevocableSubkey) { if(iKeySize % 1024 != 0) throw new Exception("Keysize must be a 1024 multiple"); System.Security.Cryptography.RandomNumberGenerator rngRand; // let's first create the encryption key BigInteger[][] biEncryptionKey; if (keyType == 1) { // it's a RSA/DSA key biEncryptionKey = GenerateRSAEncryptionKey(iKeySize); } else { // it's an elgamal/DSA key DEFAULF biEncryptionKey = GenerateElGamalEncryptionKey(iKeySize); } // now the signature key BigInteger[][] biSignatureKey = GenerateDSASignatureKey(); PublicKeyPacket pkpSignatureKey = new PublicKeyPacket(false); pkpSignatureKey.Algorithm = AsymAlgorithms.DSA; pkpSignatureKey.KeyMaterial = biSignatureKey[0]; pkpSignatureKey.TimeCreated = DateTime.Now; pkpSignatureKey.Version = PublicKeyPacketVersionNumbers.v4; SecretKeyPacket skpSignatureKey = new SecretKeyPacket(false); skpSignatureKey.SymmetricalAlgorithm = SymAlgorithms.AES256; skpSignatureKey.PublicKey = pkpSignatureKey; skpSignatureKey.InitialVector = new byte[CipherHelper.CipherBlockSize(SymAlgorithms.AES256)]; rngRand = System.Security.Cryptography.RandomNumberGenerator.Create(); rngRand.GetBytes(skpSignatureKey.InitialVector); skpSignatureKey.EncryptKeyMaterial(biSignatureKey[1], strPassphrase); skpSignatureKey.PublicKey = pkpSignatureKey; PublicKeyPacket pkpEncryptionKey = new PublicKeyPacket(true); if (keyType == 0) { // it's an elgamal/DSA key pkpEncryptionKey.Algorithm = AsymAlgorithms.ElGamal_Encrypt_Only; } else if (keyType == 1) { // it's a RSA/DSA key pkpEncryptionKey.Algorithm = AsymAlgorithms.RSA_Encrypt_Only; } pkpEncryptionKey.KeyMaterial = biEncryptionKey[0]; pkpEncryptionKey.TimeCreated = DateTime.Now; pkpEncryptionKey.Version = PublicKeyPacketVersionNumbers.v4; SecretKeyPacket skpEncryptionKey = new SecretKeyPacket(true); skpEncryptionKey.SymmetricalAlgorithm = SymAlgorithms.AES256; skpEncryptionKey.PublicKey = pkpEncryptionKey; skpEncryptionKey.InitialVector = new byte[CipherHelper.CipherBlockSize(SymAlgorithms.AES256)]; rngRand = System.Security.Cryptography.RandomNumberGenerator.Create(); rngRand.GetBytes(skpEncryptionKey.InitialVector); skpEncryptionKey.EncryptKeyMaterial(biEncryptionKey[1], strPassphrase); skpEncryptionKey.PublicKey = pkpEncryptionKey; CertifiedUserID cuiUID = new CertifiedUserID(); UserIDPacket uipUID = new UserIDPacket(); uipUID.UserID = userID.Trim() + " <" + email.Trim() + ">"; cuiUID.UserID = uipUID; SignaturePacket spSelfSig = new SignaturePacket(); if (notation != null) { SignatureSubPacket sspNotation = new SignatureSubPacket(); sspNotation.Type = SignatureSubPacketTypes.NotationData; sspNotation.NotationName = "PersonalData"; sspNotation.NotationValue = notation; spSelfSig.AddSubPacket(sspNotation,false); } if (expirationTime.Ticks != 0) { SignatureSubPacket sspExpiration = new SignatureSubPacket(); sspExpiration.Type = SignatureSubPacketTypes.KeyExpirationTime; sspExpiration.KeyExpirationTime = new DateTime(expirationTime.Ticks + (new DateTime(1970,1,2)).Ticks - pkpEncryptionKey.TimeCreated.Ticks); spSelfSig.AddSubPacket(sspExpiration, true); } if (!isRevocableKey) { SignatureSubPacket sspRevocable = new SignatureSubPacket(); sspRevocable.Type = SignatureSubPacketTypes.Revocable; sspRevocable.Revocable = isRevocableKey; spSelfSig.AddSubPacket(sspRevocable, true); } SignatureSubPacket sspPrimaryUID = new SignatureSubPacket(); sspPrimaryUID.Type = SignatureSubPacketTypes.PrimaryUserID; sspPrimaryUID.Revocable = true; spSelfSig.AddSubPacket(sspPrimaryUID, true); spSelfSig.Version = SignaturePacketVersionNumbers.v4; spSelfSig.HashAlgorithm = HashAlgorithms.SHA1; spSelfSig.KeyID = pkpSignatureKey.KeyID; spSelfSig.TimeCreated = DateTime.Now; SignatureSubPacket sspPrimaryUserID = new SignatureSubPacket(); sspPrimaryUserID.Type = SignatureSubPacketTypes.PrimaryUserID; sspPrimaryUserID.PrimaryUserID = true; spSelfSig.AddSubPacket(sspPrimaryUserID, true); SignatureSubPacket sspPreferedSymAlgos = new SignatureSubPacket(); sspPreferedSymAlgos.Type = SignatureSubPacketTypes.PreferedSymmetricAlgorithms; sspPreferedSymAlgos.PreferedSymAlgos = new SymAlgorithms[] {SymAlgorithms.AES256, SymAlgorithms.AES192, SymAlgorithms.AES256, SymAlgorithms.CAST5, SymAlgorithms.Triple_DES}; spSelfSig.AddSubPacket(sspPreferedSymAlgos, true); SignatureSubPacket sspPreferedHashAlgos = new SignatureSubPacket(); sspPreferedHashAlgos.Type = SignatureSubPacketTypes.PreferedHashAlgorithms; sspPreferedHashAlgos.PreferedHashAlgos = new HashAlgorithms[] {HashAlgorithms.SHA1}; spSelfSig.AddSubPacket(sspPreferedHashAlgos, true); cuiUID.Certificates = new System.Collections.ArrayList(); cuiUID.Sign(spSelfSig, skpSignatureKey, strPassphrase, pkpSignatureKey); CertifiedPublicSubkey cpsEncryptionKey = new CertifiedPublicSubkey(); cpsEncryptionKey.Subkey = pkpEncryptionKey; cpsEncryptionKey.SignKeyBindingSignature(pkpSignatureKey, skpSignatureKey, strPassphrase, expirationTime, isRevocableSubkey); TransportablePublicKey tpkPublicKey = new TransportablePublicKey(); tpkPublicKey.PrimaryKey = pkpSignatureKey; tpkPublicKey.SubKeys.Add(cpsEncryptionKey); tpkPublicKey.Certifications.Add(cuiUID); this.PublicRing.AddPublicKey(tpkPublicKey); TransportableSecretKey tskSecretKey = new TransportableSecretKey(); tskSecretKey.PrimaryKey = skpSignatureKey; tskSecretKey.SubKeys.Add(skpEncryptionKey); tskSecretKey.UserIDs.Add(uipUID); this.SecretRing.AddSecretKey(tskSecretKey); }
/// <summary> /// Adds a userID to the specified key /// </summary> /// <param name="userID">user id to be added</param> /// <param name="email">user email address</param> /// <param name="infos">xml encoded user infos</param> /// <param name="strPassphrase">passphrase of the secret key we want to add the user id to</param> /// <param name="KeyID">keyID of the key we want to add the userID to</param> /// <param name="isRevocable">is a revocable keyID</param> public void AddUserID(string userID, string email, string infos, string strPassphrase, ulong KeyID, bool isRevocable) { TransportablePublicKey tpkKey = this.PublicRing.Find(KeyID,false); TransportableSecretKey tskKey = this.SecretRing.Find(KeyID); if (tpkKey != null && tskKey != null) { CertifiedUserID cuiUID = new CertifiedUserID(); UserIDPacket uipUID = new UserIDPacket(); uipUID.UserID = userID.Trim() + " <" + email.Trim() + ">"; cuiUID.UserID = uipUID; SecretKeyPacket skpSignatureKey = tskKey.FindKey(AsymActions.Sign); SignaturePacket spSelfSig = new SignaturePacket(); if (infos != null) { SignatureSubPacket sspNotation = new SignatureSubPacket(); sspNotation.Type = SignatureSubPacketTypes.NotationData; sspNotation.NotationName = "PersonalData"; sspNotation.NotationValue = infos; spSelfSig.AddSubPacket(sspNotation,false); } if (!isRevocable) { SignatureSubPacket sspRevocable = new SignatureSubPacket(); sspRevocable.Type = SignatureSubPacketTypes.Revocable; sspRevocable.Revocable = isRevocable; spSelfSig.AddSubPacket(sspRevocable, true); } SignatureSubPacket sspPrimaryUID = new SignatureSubPacket(); sspPrimaryUID.Type = SignatureSubPacketTypes.PrimaryUserID; sspPrimaryUID.Revocable = false; spSelfSig.AddSubPacket(sspPrimaryUID, true); spSelfSig.Version = SignaturePacketVersionNumbers.v4; spSelfSig.HashAlgorithm = HashAlgorithms.SHA1; spSelfSig.KeyID = skpSignatureKey.PublicKey.KeyID; spSelfSig.TimeCreated = DateTime.Now; cuiUID.Certificates = new System.Collections.ArrayList(); cuiUID.Sign(spSelfSig, skpSignatureKey, strPassphrase, tpkKey.PrimaryKey); tpkKey.Certifications.Add(cuiUID); tskKey.UserIDs.Add(uipUID); return; } throw new Exception("Keys not found"); }
public void AddUserID(ulong lKeyID, string strName, string strEmail, string strPassphrase) { TransportableSecretKey tskKey = skrKeyRing.Find(lKeyID); TransportablePublicKey tpkKey = pkrKeyRing.Find(lKeyID, false); CertifiedUserID cuiUID = new CertifiedUserID(); UserIDPacket uipUID = new UserIDPacket(); uipUID.UserID = strName.Trim() + " <" + strEmail.Trim() + ">"; cuiUID.UserID = uipUID; SecretKeyPacket skpSignatureKey = tskKey.FindKey(AsymActions.Sign); SignaturePacket spSelfSig = new SignaturePacket(); spSelfSig.Version = SignaturePacketVersionNumbers.v4; spSelfSig.HashAlgorithm = HashAlgorithms.SHA1; spSelfSig.KeyID = skpSignatureKey.PublicKey.KeyID; spSelfSig.TimeCreated = DateTime.Now; cuiUID.Certificates = new System.Collections.ArrayList(); cuiUID.Sign(spSelfSig, skpSignatureKey, strPassphrase, tpkKey.PrimaryKey); tpkKey.Certifications.Add(cuiUID); tskKey.UserIDs.Add(uipUID); }
public void GenerateKey(string strName, string strEmail, string strKeyType, int iKeySize, long lExpiration, string strPassphrase) { if (strKeyType == "ElGamal/DSA") { System.Security.Cryptography.RandomNumberGenerator rngRand = System.Security.Cryptography.RandomNumberGenerator.Create(); // let's first create the encryption key BigInteger[][] biEncryptionKey = GenerateEncryptionKey(iKeySize); // now the signature key BigInteger[][] biSignatureKey = GenerateSignatureKey(); PublicKeyPacket pkpSignatureKey = new PublicKeyPacket(false); pkpSignatureKey.Algorithm = AsymAlgorithms.DSA; pkpSignatureKey.KeyMaterial = biSignatureKey[0]; pkpSignatureKey.TimeCreated = DateTime.Now; pkpSignatureKey.Version = PublicKeyPacketVersionNumbers.v4; SecretKeyPacket skpSignatureKey = new SecretKeyPacket(false); skpSignatureKey.SymmetricalAlgorithm = SymAlgorithms.AES256; skpSignatureKey.PublicKey = pkpSignatureKey; skpSignatureKey.InitialVector = new byte[CipherHelper.CipherBlockSize(SymAlgorithms.AES256)]; rngRand.GetBytes(skpSignatureKey.InitialVector); skpSignatureKey.EncryptKeyMaterial(biSignatureKey[1], strPassphrase); skpSignatureKey.PublicKey = pkpSignatureKey; PublicKeyPacket pkpEncryptionKey = new PublicKeyPacket(true); pkpEncryptionKey.Algorithm = AsymAlgorithms.ElGamal_Encrypt_Only; pkpEncryptionKey.KeyMaterial = biEncryptionKey[0]; pkpEncryptionKey.TimeCreated = DateTime.Now; pkpEncryptionKey.Version = PublicKeyPacketVersionNumbers.v4; SecretKeyPacket skpEncryptionKey = new SecretKeyPacket(true); skpEncryptionKey.SymmetricalAlgorithm = SymAlgorithms.AES256; skpEncryptionKey.PublicKey = pkpEncryptionKey; skpEncryptionKey.InitialVector = new byte[CipherHelper.CipherBlockSize(SymAlgorithms.AES256)]; rngRand.GetBytes(skpEncryptionKey.InitialVector); skpEncryptionKey.EncryptKeyMaterial(biEncryptionKey[1], strPassphrase); skpEncryptionKey.PublicKey = pkpEncryptionKey; CertifiedUserID cuiUID = new CertifiedUserID(); UserIDPacket uipUID = new UserIDPacket(); uipUID.UserID = strName.Trim() + " <" + strEmail.Trim() + ">"; cuiUID.UserID = uipUID; SignaturePacket spSelfSig = new SignaturePacket(); spSelfSig.Version = SignaturePacketVersionNumbers.v4; spSelfSig.HashAlgorithm = HashAlgorithms.SHA1; spSelfSig.KeyID = pkpSignatureKey.KeyID; spSelfSig.TimeCreated = DateTime.Now; SignatureSubPacket sspPrimaryUserID = new SignatureSubPacket(); sspPrimaryUserID.Type = SignatureSubPacketTypes.PrimaryUserID; sspPrimaryUserID.PrimaryUserID = true; spSelfSig.AddSubPacket(sspPrimaryUserID, true); SignatureSubPacket sspPreferedSymAlgos = new SignatureSubPacket(); sspPreferedSymAlgos.Type = SignatureSubPacketTypes.PreferedSymmetricAlgorithms; sspPreferedSymAlgos.PreferedSymAlgos = new SymAlgorithms[] {SymAlgorithms.AES256, SymAlgorithms.AES192, SymAlgorithms.AES256, SymAlgorithms.CAST5, SymAlgorithms.Triple_DES}; spSelfSig.AddSubPacket(sspPreferedSymAlgos, true); SignatureSubPacket sspPreferedHashAlgos = new SignatureSubPacket(); sspPreferedHashAlgos.Type = SignatureSubPacketTypes.PreferedHashAlgorithms; sspPreferedHashAlgos.PreferedHashAlgos = new HashAlgorithms[] {HashAlgorithms.SHA1}; spSelfSig.AddSubPacket(sspPreferedHashAlgos, true); if (lExpiration != 0) { SignatureSubPacket sspExpiration = new SignatureSubPacket(); sspExpiration.Type = SignatureSubPacketTypes.SignatureExpirationTime; sspExpiration.SignatureExpirationTime = new DateTime(lExpiration); spSelfSig.AddSubPacket(sspExpiration, true); } cuiUID.Certificates = new System.Collections.ArrayList(); cuiUID.Sign(spSelfSig, skpSignatureKey, strPassphrase, pkpSignatureKey); CertifiedPublicSubkey cpsEncryptionKey = new CertifiedPublicSubkey(); cpsEncryptionKey.Subkey = pkpEncryptionKey; cpsEncryptionKey.SignKeyBindingSignature(pkpSignatureKey, skpSignatureKey, strPassphrase, new DateTime(lExpiration), true); TransportablePublicKey tpkPublicKey = new TransportablePublicKey(); tpkPublicKey.PrimaryKey = pkpSignatureKey; tpkPublicKey.SubKeys.Add(cpsEncryptionKey); tpkPublicKey.Certifications.Add(cuiUID); TransportableSecretKey tskSecretKey = new TransportableSecretKey(); tskSecretKey.PrimaryKey = skpSignatureKey; tskSecretKey.SubKeys.Add(skpEncryptionKey); tskSecretKey.UserIDs.Add(uipUID); this.pkrKeyRing.AddPublicKey(tpkPublicKey); this.skrKeyRing.AddSecretKey(tskSecretKey); pkrKeyRing.Save(); skrKeyRing.Save(); // it's an RSA key } else if (strKeyType == "RSA") { } }
/// <summary> /// Parses a single packet out of the given binary /// data. Even if there are more than one packets in the byte /// array, only the first packet is returned. /// </summary> /// <param name="bBinaryData">A byte array containing a set /// of OpenPGP packets</param> /// <returns>Returns an single OpenPGP packets</returns> /// <remarks>No remarks</remarks> public virtual Packet ParsePacket(byte[] bBinaryData) { Packet pReturnPacket = new Packet(); if ((bBinaryData[0] & 0xC0) == 0xC0) { pfFormat = PacketFormats.New; } else if ((bBinaryData[0] & 0xC0) == 0x80) { pfFormat = PacketFormats.Old; } else { throw(new ArgumentException("This is not a valid OpenPGP Packet")); } if (pfFormat == PacketFormats.New) { int iBinaryDataPos = 1; ctContent = (ContentTypes)(bBinaryData[0] & 0x3F); lLength = bBinaryData[1]; bBody = new byte[0]; int iHeaderLength = 1; //partial body lengths while ((lLength > 223) && (lLength < 255)) { iBinaryDataPos += 1; iHeaderLength++; int lPartialBody = 1 << ((int)(lLength & 0x1F)); int lOldLength = 0; if (bBody.Length > 0) { byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lPartialBody]; bOldBody.CopyTo(bBody, 0); lOldLength = bBody.Length; } else { bBody = new byte[lPartialBody]; } Array.Copy(bBinaryData, iBinaryDataPos, bBody, bBody.Length - lPartialBody, lPartialBody); lLength = bBinaryData[iBinaryDataPos + lPartialBody]; iBinaryDataPos += lPartialBody; } //partial bodies must end with a normal header! if (lLength < 192) { iHeaderLength++; bHeader = new byte[iHeaderLength]; if (bBody.Length == 0) { Array.Copy(bBinaryData, 0, bHeader, 0, 2); iBinaryDataPos = 1; } byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lLength]; bOldBody.CopyTo(bBody, 0); Array.Copy(bBinaryData, iBinaryDataPos + 1, bBody, bBody.Length - (int)lLength, (int)lLength); } else if ((lLength > 191) && (lLength < 224)) { iHeaderLength += 2; bHeader = new byte[iHeaderLength]; if (bBody.Length == 0) { Array.Copy(bBinaryData, 0, bHeader, 0, 3); iBinaryDataPos = 1; } lLength = ((bBinaryData[iBinaryDataPos++] - 192) << 8) + bBinaryData[iBinaryDataPos++] + 192; byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lLength]; bOldBody.CopyTo(bBody, 0); Array.Copy(bBinaryData, iBinaryDataPos, bBody, bBody.Length - (int)lLength, (int)lLength); } else if (lLength == 255) { iHeaderLength += 5; bHeader = new byte[iHeaderLength]; if (bBody.Length == 0) { Array.Copy(bBinaryData, 0, bHeader, 0, 6); iBinaryDataPos = 1; } lLength = (bBinaryData[iBinaryDataPos++] << 24) ^ (bBinaryData[iBinaryDataPos++] << 16) ^ (bBinaryData[iBinaryDataPos++] << 8) ^ bBinaryData[iBinaryDataPos++]; byte[] bOldBody = new byte[bBody.Length]; bBody.CopyTo(bOldBody, 0); bBody = new byte[bOldBody.Length + lLength]; bOldBody.CopyTo(bBody, 0); Array.Copy(bBinaryData, iBinaryDataPos, bBody, bBody.Length - (int)lLength, (int)lLength); } } else { ctContent = (ContentTypes)((bBinaryData[0] & 0x3C) >> 2); switch (bBinaryData[0] & 0x03) { case 0: lLength = bBinaryData[1]; bHeader = new byte[2]; break; case 1: lLength = (bBinaryData[1] << 8) ^ (bBinaryData[2]); bHeader = new byte[3]; break; case 2: lLength = (bBinaryData[1] << 16) ^ (bBinaryData[2] << 8) ^ (bBinaryData[3]); bHeader = new byte[4]; break; case 3: throw new System.NotSupportedException("Packets of indetermined length are not supported due to security considerations!"); default: throw new System.ApplicationException("This is not a valid Packet!"); } bBody = new byte[lLength]; Array.Copy(bBinaryData, 0, bHeader, 0, bHeader.Length); Array.Copy(bBinaryData, bHeader.Length, bBody, 0, (int)lLength); } this.bIsUpdated = false; switch (ctContent) { case ContentTypes.AsymSessionKey: pReturnPacket = new AsymSessionKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Compressed: pReturnPacket = new CompressedDataPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.LiteralData: pReturnPacket = new LiteralDataPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Marker: pReturnPacket = new Packet(this); //We can savly ignore Marker packets! //MessageBox.Show("This is a marker packet. It is not yet supported."); break; case ContentTypes.OnePassSignature: pReturnPacket = new OnePassSignaturePacket(this); //System.Windows.Forms.MessageBox.Show("This is a One Pass Signature Packet. It is not yet supported"); break; //Content is Public Key Packet case ContentTypes.PublicKey: pReturnPacket = new PublicKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; //Content is Public Subkey Packet. Same format as Public Key Packet case ContentTypes.PublicSubkey: pReturnPacket = new PublicKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SecretKey: pReturnPacket = new SecretKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SecretSubkey: pReturnPacket = new SecretKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Signature: pReturnPacket = new SignaturePacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SymEncrypted: pReturnPacket = new SymmetricallyEncryptedDataPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.SymSessionKey: pReturnPacket = new SymSessionKeyPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; case ContentTypes.Trust: pReturnPacket = new Packet(this); //throw new Exception("This is a Trust Packet. It is not yet supported"); break; case ContentTypes.UserID: pReturnPacket = new UserIDPacket(this); pReturnPacket = pReturnPacket.ParsePacket(bBody); break; default: pReturnPacket = new Packet(this); //throw new Exception("Sorry, but this is a packet I don't know about!"); break; } pReturnPacket.bIsUpdated = false; return pReturnPacket; }