public static UserID Parse(Packet input)
        {
            UserID uid = (UserID)input;

            uid.Value = Encoding.UTF8.GetString(uid.RawData,0,uid.RawData.Length);

            return uid;
        }
        private static Packet DispatchPacket(Packet packet)
        {
            Type t = Type.GetType("ActiveUp.Net.Security.OpenPGP.Packets." + packet.Type.ToString());
            object pack = null;
#if !PocketPC
            pack = System.Activator.CreateInstance("ActiveUp.Mail", "ActiveUp.Net.Security.OpenPGP.Packets." + packet.Type.ToString()).Unwrap();
#else
            pack = System.Activator.CreateInstance(t);
#endif
            return (Packet)t.GetMethod("Parse").Invoke(pack, new object[] { packet });
        }
        public new static SecretKey Parse(Packet input)
        {
            SecretKey sk = (SecretKey)input;

            sk = (SecretKey)PublicKey.Parse(input);

            MemoryStream ms = new MemoryStream(sk.RawData);
            ms.Position = sk.TempPosition;
            // String to key usage ?
            byte s2kUsage = (byte)ms.ReadByte();

            if (s2kUsage == 255 || s2kUsage == 254)
            {
                // We'll be using String to key...but with which algorithm ?
                sk.SymmetricKeyAlgorithm = (SymmetricKeyAlgorithm)ms.ReadByte();
                // And which type of S2K ?
                sk.StringToKeySpecifierType = (StringToKeySpecifierType)ms.ReadByte();
                sk.InitialVector = new byte[Constants.GetCipherBlockSize(sk.SymmetricKeyAlgorithm)];
                ms.Read(sk.InitialVector, 0, sk.InitialVector.Length);
                
            }
            else if (s2kUsage == 0)
            {

            }
            else
            {
                sk.SymmetricKeyAlgorithm = (SymmetricKeyAlgorithm)s2kUsage;
                sk.InitialVector = new byte[Constants.GetCipherBlockSize(sk.SymmetricKeyAlgorithm)];
                ms.Read(sk.InitialVector, 0, sk.InitialVector.Length);
            }

            // MPIs
            int mpiMaxCount = Constants.GetTotalMPICount(sk.PublicKeyAlgorithm);

            while (ms.Position < ms.Length && sk.MPIs.Count < mpiMaxCount)
            {
                byte first = (byte)ms.ReadByte();
                byte second = (byte)ms.ReadByte();
                short length = (short)((Converter.ToShort(new byte[2] { first, second }) + 7) / 8);
                byte[] mpi = new byte[(int)length];
                ms.Read(mpi, 0, length);
                sk.MPIs.Add(mpi);
            }

            sk.CheckSum = new byte[2];
            ms.Read(sk.CheckSum, 0, 2);
            
            return sk;
        }
        // TODO : Clés spécifiques à l'algorithme

        public static PublicKeyEncryptedSessionKey Parse(Packet input)
        {
            PublicKeyEncryptedSessionKey pkesk = (PublicKeyEncryptedSessionKey)input;
            byte[] content = pkesk.RawData;
            pkesk.VersionNumber = content[0];
            
            byte[] keyID = new byte[8];
            Array.Copy(content, 1, keyID, 0, 8);
            //ActiveUp.Net.Mail.Logger.AddEntry(Encoding.ASCII.GetString(keyID));
            pkesk.KeyID = Converter.ToULong(keyID);

            pkesk.PublicKeyAlgorithm = (PublicKeyAlgorithm)content[9];

            return pkesk;
        }
        public static PublicKey Parse(Packet input)
        {
            PublicKey pk = (PublicKey)input;

            MemoryStream ms = new MemoryStream(pk.RawData);

            pk.VersionNumber = ms.ReadByte();

            byte[] creation = new byte[4];
            ms.Read(creation, 0, 4);
            pk.CreationTime = Converter.UnixTimeStampToDateTime(Converter.ToInt(creation));

            if (pk.VersionNumber.Equals(3))
            {
                byte[] validity = new byte[2];
                ms.Read(validity, 0, 2);
                pk.Validity = (int)Converter.ToShort(validity);
            }

            pk.PublicKeyAlgorithm = (PublicKeyAlgorithm)ms.ReadByte();

            // MPIs
            int mpiMaxCount = Constants.GetPublicMPICount(pk.PublicKeyAlgorithm);
            
            while (ms.Position < ms.Length && pk.MPIs.Count < mpiMaxCount)
            {
                byte first = (byte)ms.ReadByte();
                byte second = (byte)ms.ReadByte();
                short length = (short)((Converter.ToShort(new byte[2] { first, second }) + 7) / 8);
                byte[] mpi = new byte[(int)length];
                ms.Read(mpi, 0, length);
                pk.MPIs.Add(mpi);
            }

            pk.TempPosition = (int)ms.Position;

            return pk;
        }
 public new static PublicSubkey Parse(Packet input)
 {
     return (PublicSubkey)PublicKey.Parse(input);
 }
        private static Packet GetNextPacket(ref MemoryStream stream)
        {
            Packet packet = new Packet();

            byte firstbyte = (byte)stream.ReadByte();
            string first = ToBitString(firstbyte);
            if (!first[0].Equals('1')) throw new InvalidPacketSyntaxException("First byte's first bit is 0.");

            PacketFormat format = (PacketFormat)Int32.Parse(first[1].ToString());

            MemoryStream outstream = new MemoryStream();
            
            if (format.Equals(PacketFormat.Old))
            {
                PacketType type = (PacketType)((firstbyte & 60) >> 2);

#if !PocketPC
                packet = (Packet)(System.Activator.CreateInstance("ActiveUp.Mail", "ActiveUp.Net.Security.OpenPGP.Packets."+type.ToString()).Unwrap());
#else
                packet = (Packet)(System.Activator.CreateInstance(Type.GetType("ActiveUp.Net.Security.OpenPGP.Packets."+type.ToString())));
#endif

                //ActiveUp.Net.Mail.Logger.AddEntry("Packet : "+packet.ToString());

                packet.Format = format;
                packet.Type = type;

                byte lengthType = (byte)(firstbyte & 3);
                byte next = (byte)stream.ReadByte();
                if (lengthType == 0) 
                {
                    packet.BodyLength = next;
                    packet.TotalLength = packet.BodyLength + 2;
                }
                else if (lengthType == 1)
                {
                    byte nextnext = (byte)stream.ReadByte();
                    packet.BodyLength = (next << 8) + nextnext;
                    packet.TotalLength = packet.BodyLength + 3;
                }
                else if (lengthType == 2)
                {
                    // A VERIFIER !
                    byte nextnext = (byte)stream.ReadByte();
                    byte nextnextnext = (byte)stream.ReadByte();
                    byte nextnextnextnext = (byte)stream.ReadByte();
                    packet.BodyLength = (next << 24) + (nextnext << 16) + (nextnextnext << 8) + nextnextnextnext;
                    packet.TotalLength = packet.BodyLength + 5;
                }
                else if (lengthType == 3) packet.TotalLength = packet.BodyLength + 1;
                else throw new InvalidPacketSyntaxException("Invalid old format packet length type : "+lengthType.ToString());
                outstream.Write(stream.ToArray(), (int)stream.Position, packet.BodyLength);
                stream.Position += packet.BodyLength;
            }
            if (format.Equals(PacketFormat.New))
            {
                PacketType type = (PacketType)(firstbyte & 63);
                
                #if !PocketPC
                packet = (Packet)(System.Activator.CreateInstance("ActiveUp.Mail", "ActiveUp.Net.Security.OpenPGP.Packets." + type.ToString()).Unwrap());
                #else
                packet = (Packet)(System.Activator.CreateInstance(Type.GetType("ActiveUp.Net.Security.OpenPGP.Packets." + type.ToString())));
                #endif
                
                packet.Format = format;
                packet.Type = type;

                AddNextPacketNewFormat(ref packet, ref stream, ref outstream);
            }
            packet.RawData = outstream.ToArray();
            outstream.Close();

#if !PocketPC
            outstream.Dispose();
#endif
            return packet;
        }
 private static void AddNextPacketNewFormat(ref Packet packet, ref MemoryStream stream, ref MemoryStream outstream)
 {
     byte next = (byte)stream.ReadByte();
     int length = 0;
     if (next < 192)
     {
         length = next;
         packet.BodyLength += next;
         packet.TotalLength += packet.BodyLength + 2;
     }
     else if (next > 191 && next < 223)
     {
         byte nextnext = (byte)stream.ReadByte();
         length = ((next - 192) << 8) + nextnext + 192;
         packet.BodyLength += length;
         packet.TotalLength += packet.BodyLength + 3;
     }
     else if (next == 255)
     {
         int nextnext = stream.ReadByte();
         int nextnextnext = stream.ReadByte();
         int nextnextnextnext = stream.ReadByte();
         int nextnextnextnextnext = stream.ReadByte();
         length = (nextnext << 24) | (nextnextnext << 16) | (nextnextnextnext << 8) | nextnextnextnextnext;
         packet.BodyLength += length;
         packet.TotalLength += packet.BodyLength + 6;
     }
     else if (next > 223 && next < 255)
     {
         int partlength = (1 << (next & 31));
         packet.BodyLength += partlength;
         packet.TotalLength += partlength + 1;
         outstream.Write(stream.ToArray(), (int)stream.Position, partlength);
         stream.Position += partlength;
         AddNextPacketNewFormat(ref packet, ref stream, ref outstream);
         return;
     }
     outstream.Write(stream.ToArray(), (int)stream.Position, length);
     stream.Position += packet.BodyLength;
 }
 public new static SecretSubkey Parse(Packet input)
 {
     return (SecretSubkey)SecretKey.Parse(input);
 }
        public static Signature Parse(Packet input)
        {
            Signature sig = (Signature)input;
            
            MemoryStream ms = new MemoryStream(sig.RawData);
            //ActiveUp.Net.Mail.Logger.AddEntry(sig.RawData.Length.ToString());
            //ActiveUp.Net.Mail.Logger.AddEntry(ms.Length.ToString());
            sig.VersionNumber = ms.ReadByte();

            int next = ms.ReadByte();
            if (sig.VersionNumber.Equals(3))
            {
                if (!next.Equals(5)) throw new InvalidPacketSyntaxException("Invalid syntax for a version 3 signature packet. Second byte is not 5.");
                else
                {
                    sig.Type = (SignatureType)ms.ReadByte();

                    byte[] creation = new byte[4];
                    ms.Read(creation, 0, 4);
                    sig.CreationTime = Converter.UnixTimeStampToDateTime(Converter.ToInt(creation));

                    byte[] keyID = new byte[8];
                    ms.Read(keyID, 0, 8);
                    sig.IssuerKeyID = Converter.ToULong(keyID);
                }
            }
            else
            {
                // Vérifier tout avec une signature V4 !
                sig.Type = (SignatureType)next;
            }
            sig.PublicKeyAlgorithm = (PublicKeyAlgorithm)ms.ReadByte();
            sig.HashAlgorithm = (HashAlgorithm)ms.ReadByte();

            // Add version 4 subpackets
            if (sig.VersionNumber.Equals(4))
            {
                // Hashed subpackets
                byte[] hashedsublengthbytes = new byte[2];
                ms.Read(hashedsublengthbytes, 0, 2);
                short hashedsublength = Converter.ToShort(hashedsublengthbytes);
                while (ms.Position < 5 + hashedsublength)
                    sig.HashedSubPackets.Add(GetNextSignatureSubPacket(ref ms));

                // Unhashed subpackets
                byte[] unhashedsublengthbytes = new byte[2];
                ms.Read(unhashedsublengthbytes, 0, 2);
                short unhashedsublength = Converter.ToShort(unhashedsublengthbytes);
                while (ms.Position < hashedsublength + unhashedsublength)
                    sig.UnHashedSubPackets.Add(GetNextSignatureSubPacket(ref ms));

                // Fill properties
                List<SignatureSubPacket> allSubPackets = new List<SignatureSubPacket>();
                allSubPackets.AddRange(sig.HashedSubPackets);
                allSubPackets.AddRange(sig.UnHashedSubPackets);
                foreach (SignatureSubPacket spacket in allSubPackets)
                {
                    if (spacket.Type.Equals(SignatureSubPacketType.CreationTime))
                        sig.CreationTime = Converter.UnixTimeStampToDateTime(Converter.ToInt(spacket.Value));
                    else if (spacket.Type.Equals(SignatureSubPacketType.KeyExpirationTime))
                        sig.KeyExpiration = Converter.UnixTimeStampToDateTime(Converter.ToInt(spacket.Value));
                    else if (spacket.Type.Equals(SignatureSubPacketType.ExpirationTime))
                        sig.SignatureExpiration = Converter.UnixTimeStampToDateTime(Converter.ToInt(spacket.Value));
                    else if (spacket.Type.Equals(SignatureSubPacketType.ExportableCertification))
                        sig.IsExportableCertification = (spacket.Value[0] == 1);
                    else if (spacket.Type.Equals(SignatureSubPacketType.Revocable))
                        sig.IsRevocable = (spacket.Value[0] == 1);
                    else if (spacket.Type.Equals(SignatureSubPacketType.TrustSignature))
                    {
                        sig.Trust.Level = (TrustLevel)spacket.Value[0];
                        sig.Trust.Amount = spacket.Value[1];
                    }
                    else if (spacket.Type.Equals(SignatureSubPacketType.RegularExpression))
                        sig.RegularExpression = spacket.Value;
                    else if (spacket.Type.Equals(SignatureSubPacketType.RevocationKey))
                    {
                        if ((spacket.Value[0] & 128) != 128) throw new InvalidPacketSyntaxException("First bit of revocation key class is 0");
                        sig.RevocationKey.Class = (RevocationKeyClass)(spacket.Value[0] & 64);
                        sig.RevocationKey.HashAlgorithm = (HashAlgorithm)spacket.Value[1];
                        Array.Copy(spacket.Value, 2, sig.RevocationKey.FingerPrint, 0, 20);
                    }
                    else if (spacket.Type.Equals(SignatureSubPacketType.NotationData))
                    {
                        Notation n = new Notation();
                        n.IsHumanReadable = ((spacket.Value[0] & 128) == 128);
                        byte[] nameLength = new byte[2];
                        Array.Copy(spacket.Value, 4, nameLength, 0, 2);
                        Array.Copy(spacket.Value, 6, n.Name, 0, Converter.ToInt(nameLength));
                        byte[] valueLength = new byte[2];
                        Array.Copy(spacket.Value, 6 + Converter.ToInt(nameLength), valueLength, 0, 2);
                        Array.Copy(spacket.Value, 6 + Converter.ToInt(nameLength) + 2, n.Value, 0, Converter.ToInt(valueLength));
                        sig.Notations.Add(n);
                    }
                    else if (spacket.Type.Equals(SignatureSubPacketType.PolicyURL))
                        sig.PolicyURL = Encoding.ASCII.GetString(spacket.Value,0,spacket.Value.Length);
                    else if (spacket.Type.Equals(SignatureSubPacketType.SignerUserID))
                        sig.SignerUserID = Encoding.ASCII.GetString(spacket.Value,0,spacket.Value.Length);
                    else if (spacket.Type.Equals(SignatureSubPacketType.SignatureTarget))
                    {
                        sig.TargetSignatureInfo.PublicKeyAlgorithm = (PublicKeyAlgorithm)spacket.Value[0];
                        sig.TargetSignatureInfo.HashAlgorithm = (HashAlgorithm)spacket.Value[1];
                        Array.Copy(spacket.Value, 2, sig.TargetSignatureInfo.Hash, 0, spacket.Value.Length - 2);
                    }
                    else if (spacket.Type.Equals(SignatureSubPacketType.EmbeddedSignature))
                    {
                        Packet embedded = new Packet();
                        embedded.RawData = spacket.Value;
                        sig.EmbeddedSignature = Signature.Parse(embedded);
                    }
                    else if (spacket.Type.Equals(SignatureSubPacketType.IssuerKeyID))
                        sig.IssuerKeyID = Converter.ToULong(spacket.Value);
                    else if (spacket.Type.Equals(SignatureSubPacketType.PrimaryUserID))
                        sig.IsPrimaryUserID = (spacket.Value[0] == 1);
                    else if (spacket.Type.Equals(SignatureSubPacketType.KeyFlags))
                    {
                        if ((spacket.Value[0] & (byte)KeyFlag.Authentication) == (int)KeyFlag.Authentication) sig.KeyFlags.Add(KeyFlag.Authentication);
                        if ((spacket.Value[0] & (byte)KeyFlag.CertifiesOtherKeys) == (int)KeyFlag.CertifiesOtherKeys) sig.KeyFlags.Add(KeyFlag.CertifiesOtherKeys);
                        if ((spacket.Value[0] & (byte)KeyFlag.EncryptsCommunications) == (int)KeyFlag.EncryptsCommunications) sig.KeyFlags.Add(KeyFlag.EncryptsCommunications);
                        if ((spacket.Value[0] & (byte)KeyFlag.EncryptsStorage) == (int)KeyFlag.EncryptsStorage) sig.KeyFlags.Add(KeyFlag.EncryptsStorage);
                        if ((spacket.Value[0] & (byte)KeyFlag.GroupKey) == (int)KeyFlag.GroupKey) sig.KeyFlags.Add(KeyFlag.GroupKey);
                        if ((spacket.Value[0] & (byte)KeyFlag.SignsData) == (int)KeyFlag.SignsData) sig.KeyFlags.Add(KeyFlag.SignsData);
                        if ((spacket.Value[0] & (byte)KeyFlag.SplitKey) == (int)KeyFlag.SplitKey) sig.KeyFlags.Add(KeyFlag.SplitKey);
                    }
                    else if (spacket.Type.Equals(SignatureSubPacketType.Features))
                    {
                        if ((spacket.Value[0] & (byte)Feature.ModificationDetection) == (int)Feature.ModificationDetection) sig.Features.Add(Feature.ModificationDetection);
                    }
                    else if (spacket.Type.Equals(SignatureSubPacketType.KeyServerPreferences))
                    {
                        if ((spacket.Value[0] & (byte)KeyServerPreference.NoModify) == (int)KeyServerPreference.NoModify) sig.KeyServerPreferences.Add(KeyServerPreference.NoModify);
                    }
                    else if (spacket.Type.Equals(SignatureSubPacketType.ReasonForRevocation))
                    {
                        if ((spacket.Value[0] & (byte)Reason.KeyCompromised) == (int)Reason.KeyCompromised) sig.ReasonForRevocation.Reason = Reason.KeyCompromised;
                        else if ((spacket.Value[0] & (byte)Reason.KeyRetired) == (int)Reason.KeyRetired) sig.ReasonForRevocation.Reason = Reason.KeyRetired;
                        else if ((spacket.Value[0] & (byte)Reason.KeySuperceded) == (int)Reason.KeySuperceded) sig.ReasonForRevocation.Reason = Reason.KeySuperceded;
                        else if ((spacket.Value[0] & (byte)Reason.UserIDNoLongerValid) == (int)Reason.UserIDNoLongerValid) sig.ReasonForRevocation.Reason = Reason.UserIDNoLongerValid;
                        else if (spacket.Value[0] == 0) sig.ReasonForRevocation.Reason = Reason.NoneSpecified;
                        byte[] comment = new byte[spacket.Value.Length - 1];
                        Array.Copy(spacket.Value, 1, comment, 0, comment.Length);
                        sig.ReasonForRevocation.Comment = Encoding.UTF8.GetString(comment,0,comment.Length);
                    }
                    else if (spacket.Type.Equals(SignatureSubPacketType.PreferredCompressionAlgorithms))
                        for (int i = 0; i < spacket.Value.Length; i++) sig.PreferredCompressionAlgorithms.Add((CompressionAlgorithm)spacket.Value[i]);
                    else if (spacket.Type.Equals(SignatureSubPacketType.PreferredHashAlgorithms))
                        for (int i = 0; i < spacket.Value.Length; i++) sig.PreferredHashAlgorithms.Add((HashAlgorithm)spacket.Value[i]);
                    else if (spacket.Type.Equals(SignatureSubPacketType.PreferredSymmetricAlgorithms))
                        for (int i = 0; i < spacket.Value.Length; i++) sig.PreferredSymmetricAlgorithms.Add((SymmetricKeyAlgorithm)spacket.Value[i]);
                }
            }

            sig.QuickCheck = new byte[2];
            ms.Read(sig.QuickCheck, 0, 2);

            // MPIs
            while (ms.Position < ms.Length)
            {
                byte first = (byte)ms.ReadByte();
                byte second = (byte)ms.ReadByte();
                short length = (short)((Converter.ToShort(new byte[2] { first, second }) + 7) / 8);
                byte[] mpi = new byte[(int)length];
                ms.Read(mpi, 0, length);
                sig.MPIs.Add(mpi);
            }

            return sig;
        }