/// <summary> /// Converts a signature to a signed packet. Take note that during this process, /// the signature will be verified based on the desired algorithm. /// </summary> /// <param name="signature">Signature to convert.</param> /// <param name="remoteIdentity">Identity of the sender of this signed packet. May not always be the signer.</param> /// <param name="signatureAlgorithm">Algorithm to verify the signature with.</param> /// <param name="packetFactory">Packet factory to create the packet from.</param> /// <returns>Signed packet.</returns> public static PacketSigned FromSignature(Signature signature, Identity remoteIdentity, SignatureAlgorithm signatureAlgorithm, PacketFactory packetFactory) { if (signatureAlgorithm == null) { throw new SecurityException("Null signature algorithm provided."); } MemoryStream signaturePacketBuffer = new MemoryStream(signature.Data); BinaryReader stream = new BinaryReader(signaturePacketBuffer); //Read the cryptographic salt from the packet, skipping it to advance forward. stream.ReadInt32(); //Read the time the signature was created. DateTime signatureDate = new DateTime(stream.ReadInt64(), DateTimeKind.Utc); //Read the ID from the packet. byte packetId = stream.ReadByte(); //Create the packet from the factory using the ID read. ReliableIM.Network.Protocol.Packet packet = packetFactory.CreateFromId(packetId); if (!(packet is PacketSigned)) { throw new SecurityException("Packet type not acceptable."); } //Set the date time instance. ((PacketSigned)packet).dateTime = signatureDate; //Read the packet contents into the factory's packet. packet.Read(stream); //Verify the packet's signature against the given algorithm. if (!((PacketSigned)packet).VerifySignature(signatureAlgorithm, signature, remoteIdentity.Equals(signatureAlgorithm.Identity))) { throw new SecurityException("Signature verification failed."); } //Warning: At this point the signature has been verified, and authenticity //of the packet's origin (regardless of route) is no longer questioned. return((PacketSigned)packet); }