private static string GetFileName(string imageUri)
 {
     var sha = new Sha256Digest();
     var stream = new DigestStream(new MemoryStream(), null, sha);
     using (var writer = new StreamWriter(stream))
     {
         writer.Write(imageUri);
     }
     byte[] buffer = new byte[sha.GetDigestSize()];
     sha.DoFinal(buffer, 0);
     string hex = BitConverter.ToString(buffer);
     string fileName = hex.Replace("-", "");
     return fileName;
 }
		public CmsTypedStream GetSignedContent()
		{
			if (_signedContent == null)
			{
				return null;
			}

			Stream digStream = _signedContent.ContentStream;

			foreach (IDigest digest in _digests.Values)
			{
				digStream = new DigestStream(digStream, digest, null);
			}

			return new CmsTypedStream(_signedContent.ContentType, digStream);
		}
		/**
		* generate a signed object that for a CMS Signed Data
		* object using the given provider - if encapsulate is true a copy
		* of the message will be included in the signature. The content type
		* is set according to the OID represented by the string signedContentType.
		* @param out stream the CMS object is to be written to.
		* @param signedContentType OID for data to be signed.
		* @param encapsulate true if data should be encapsulated.
		* @param dataOutputStream output stream to copy the data being signed to.
		*/
		public Stream Open(
			Stream	outStream,
			string	signedContentType,
			bool	encapsulate,
			Stream	dataOutputStream)
		{
			if (outStream == null)
				throw new ArgumentNullException("outStream");
			if (!outStream.CanWrite)
				throw new ArgumentException("Expected writeable stream", "outStream");
			if (dataOutputStream != null && !dataOutputStream.CanWrite)
				throw new ArgumentException("Expected writeable stream", "dataOutputStream");

			_messageDigestsLocked = true;
			
			//
            // ContentInfo
            //
            BerSequenceGenerator sGen = new BerSequenceGenerator(outStream);

			sGen.AddObject(CmsObjectIdentifiers.SignedData);

			//
            // Signed Data
            //
            BerSequenceGenerator sigGen = new BerSequenceGenerator(
				sGen.GetRawOutputStream(), 0, true);

			sigGen.AddObject(CalculateVersion(signedContentType));

			Asn1EncodableVector digestAlgs = new Asn1EncodableVector();

			foreach (string digestOid in _messageDigestOids)
            {
				digestAlgs.Add(
            		new AlgorithmIdentifier(new DerObjectIdentifier(digestOid), DerNull.Instance));
            }

            {
				byte[] tmp = new DerSet(digestAlgs).GetEncoded();
				sigGen.GetRawOutputStream().Write(tmp, 0, tmp.Length);
			}

			BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());

			eiGen.AddObject(new DerObjectIdentifier(signedContentType));

			Stream digStream;
			if (encapsulate)
            {
                BerOctetStringGenerator octGen = new BerOctetStringGenerator(
					eiGen.GetRawOutputStream(), 0, true);

				digStream = octGen.GetOctetOutputStream(_bufferSize);

				if (dataOutputStream != null)
				{
					digStream = new TeeOutputStream(dataOutputStream, digStream);
				}
            }
            else
            {
				if (dataOutputStream != null)
				{
					digStream = dataOutputStream;
				}
				else
				{
					digStream = new NullOutputStream();
				}
			}

			foreach (IDigest d in _messageDigests.Values)
			{
                digStream = new DigestStream(digStream, null, d);
            }

			return new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen);
        }
        internal Stream DoGetDataStream(byte[] rawPassPhrase, bool clearPassPhrase)
        {
			try
			{
				SymmetricKeyAlgorithmTag keyAlgorithm = keyData.EncAlgorithm;

				KeyParameter key = PgpUtilities.DoMakeKeyFromPassPhrase(
					keyAlgorithm, keyData.S2k, rawPassPhrase, clearPassPhrase);

                byte[] secKeyData = keyData.GetSecKeyData();
				if (secKeyData != null && secKeyData.Length > 0)
				{
					IBufferedCipher keyCipher = CipherUtilities.GetCipher(
						PgpUtilities.GetSymmetricCipherName(keyAlgorithm) + "/CFB/NoPadding");

					keyCipher.Init(false,
						new ParametersWithIV(key, new byte[keyCipher.GetBlockSize()]));

					byte[] keyBytes = keyCipher.DoFinal(secKeyData);

					keyAlgorithm = (SymmetricKeyAlgorithmTag) keyBytes[0];

					key = ParameterUtilities.CreateKeyParameter(
						PgpUtilities.GetSymmetricCipherName(keyAlgorithm),
						keyBytes, 1, keyBytes.Length - 1);
				}


				IBufferedCipher c = CreateStreamCipher(keyAlgorithm);

				byte[] iv = new byte[c.GetBlockSize()];

				c.Init(false, new ParametersWithIV(key, iv));

				encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c, null));

				if (encData is SymmetricEncIntegrityPacket)
				{
					truncStream = new TruncatedStream(encStream);

					string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
					IDigest digest = DigestUtilities.GetDigest(digestName);

					encStream = new DigestStream(truncStream, digest, null);
				}

				if (Streams.ReadFully(encStream, iv, 0, iv.Length) < iv.Length)
					throw new EndOfStreamException("unexpected end of stream.");

				int v1 = encStream.ReadByte();
				int v2 = encStream.ReadByte();

				if (v1 < 0 || v2 < 0)
					throw new EndOfStreamException("unexpected end of stream.");


				// Note: the oracle attack on the "quick check" bytes is not deemed
				// a security risk for PBE (see PgpPublicKeyEncryptedData)

				bool repeatCheckPassed =
						iv[iv.Length - 2] == (byte)v1
					&&	iv[iv.Length - 1] == (byte)v2;

				// Note: some versions of PGP appear to produce 0 for the extra
				// bytes rather than repeating the two previous bytes
				bool zeroesCheckPassed =
						v1 == 0
					&&	v2 == 0;

				if (!repeatCheckPassed && !zeroesCheckPassed)
				{
					throw new PgpDataValidationException("quick check failed.");
				}


				return encStream;
			}
			catch (PgpException e)
			{
				throw e;
			}
			catch (Exception e)
			{
				throw new PgpException("Exception creating cipher", e);
			}
		}
		/// <summary>
		/// <p>
		/// If buffer is non null stream assumed to be partial, otherwise the length will be used
		/// to output a fixed length packet.
		/// </p>
		/// <p>
		/// The stream created can be closed off by either calling Close()
		/// on the stream or Close() on the generator. Closing the returned
		/// stream does not close off the Stream parameter <c>outStr</c>.
		/// </p>
		/// </summary>
        private Stream Open(
            Stream	outStr,
            long	length,
            byte[]	buffer)
        {
			if (cOut != null)
				throw new InvalidOperationException("generator already in open state");
			if (methods.Count == 0)
				throw new InvalidOperationException("No encryption methods specified");
			if (outStr == null)
				throw new ArgumentNullException("outStr");

			pOut = new BcpgOutputStream(outStr);

			KeyParameter key;

			if (methods.Count == 1)
            {
                if (methods[0] is PbeMethod)
                {
                    PbeMethod m = (PbeMethod)methods[0];

					key = m.GetKey();
                }
                else
                {
                    key = PgpUtilities.MakeRandomKey(defAlgorithm, rand);

					byte[] sessionInfo = CreateSessionInfo(defAlgorithm, key);
                    PubMethod m = (PubMethod)methods[0];

                    try
                    {
                        m.AddSessionInfo(sessionInfo, rand);
                    }
                    catch (Exception e)
                    {
                        throw new PgpException("exception encrypting session key", e);
                    }
                }

				pOut.WritePacket((ContainedPacket)methods[0]);
            }
            else // multiple methods
            {
                key = PgpUtilities.MakeRandomKey(defAlgorithm, rand);
				byte[] sessionInfo = CreateSessionInfo(defAlgorithm, key);

				for (int i = 0; i != methods.Count; i++)
                {
                    EncMethod m = (EncMethod)methods[i];

                    try
                    {
                        m.AddSessionInfo(sessionInfo, rand);
                    }
                    catch (Exception e)
                    {
                        throw new PgpException("exception encrypting session key", e);
                    }

                    pOut.WritePacket(m);
                }
            }

            string cName = PgpUtilities.GetSymmetricCipherName(defAlgorithm);
			if (cName == null)
            {
                throw new PgpException("null cipher specified");
            }

			try
            {
                if (withIntegrityPacket)
                {
                    cName += "/CFB/NoPadding";
                }
                else
                {
                    cName += "/OpenPGPCFB/NoPadding";
                }

                c = CipherUtilities.GetCipher(cName);

				// TODO Confirm the IV should be all zero bytes (not inLineIv - see below)
				byte[] iv = new byte[c.GetBlockSize()];
                c.Init(true, new ParametersWithRandom(new ParametersWithIV(key, iv), rand));

                if (buffer == null)
                {
                    //
                    // we have to Add block size + 2 for the Generated IV and + 1 + 22 if integrity protected
                    //
                    if (withIntegrityPacket)
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, length + c.GetBlockSize() + 2 + 1 + 22);
                        pOut.WriteByte(1);        // version number
                    }
                    else
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, length + c.GetBlockSize() + 2, oldFormat);
                    }
                }
                else
                {
                    if (withIntegrityPacket)
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, buffer);
                        pOut.WriteByte(1);        // version number
                    }
                    else
                    {
                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, buffer);
                    }
                }

				int blockSize = c.GetBlockSize();
				byte[] inLineIv = new byte[blockSize + 2];
                rand.NextBytes(inLineIv, 0, blockSize);
				Array.Copy(inLineIv, inLineIv.Length - 4, inLineIv, inLineIv.Length - 2, 2);

				Stream myOut = cOut = new CipherStream(pOut, null, c);

				if (withIntegrityPacket)
                {
					string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
					IDigest digest = DigestUtilities.GetDigest(digestName);
					myOut = digestOut = new DigestStream(myOut, null, digest);
                }

				myOut.Write(inLineIv, 0, inLineIv.Length);

				return new WrappedGeneratorStream(this, myOut);
            }
            catch (Exception e)
            {
                throw new PgpException("Exception creating cipher", e);
            }
        }
        /**
        * generate a signed object that for a CMS Signed Data
        * object - if encapsulate is true a copy
        * of the message will be included in the signature. The content type
        * is set according to the OID represented by the string signedContentType.
        */
        public Stream Open(
            Stream	outStream,
            string	signedContentType,
            bool	encapsulate)
        {
            //
            // ContentInfo
            //
            BerSequenceGenerator sGen = new BerSequenceGenerator(outStream);

            sGen.AddObject(CmsObjectIdentifiers.SignedData);

            //
            // Signed Data
            //
            BerSequenceGenerator sigGen = new BerSequenceGenerator(
                sGen.GetRawOutputStream(), 0, true);

            sigGen.AddObject(CalculateVersion(signedContentType));

            Asn1EncodableVector digestAlgs = new Asn1EncodableVector();

            //
            // add the precalculated SignerInfo digest algorithms.
            //
            foreach (SignerInformation signer in _signers)
            {
                digestAlgs.Add(FixAlgID(signer.DigestAlgorithmID));
            }

            //
            // add the new digests
            //
            foreach (SignerInf signer in _signerInfs)
            {
                digestAlgs.Add(FixAlgID(signer.DigestAlgorithmID));
            }

            {
                byte[] tmp = new DerSet(digestAlgs).GetEncoded();
                sigGen.GetRawOutputStream().Write(tmp, 0, tmp.Length);
            }

            BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());

            eiGen.AddObject(new DerObjectIdentifier(signedContentType));

            Stream digStream;
            if (encapsulate)
            {
                BerOctetStringGenerator octGen = new BerOctetStringGenerator(
                    eiGen.GetRawOutputStream(), 0, true);

                if (_bufferSize != 0)
                {
                    digStream = octGen.GetOctetOutputStream(new byte[_bufferSize]);
                }
                else
                {
                    digStream = octGen.GetOctetOutputStream();
                }
            }
            else
            {
                digStream = new NullOutputStream();
            }

            foreach (IDigest d in _messageDigests)
            {
                digStream = new DigestStream(digStream, null, d);
            }

            return new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen);
        }
		/// <summary>Return the decrypted data stream for the packet.</summary>
        public Stream GetDataStream(
            PgpPrivateKey privKey)
        {
			byte[] plain = fetchSymmetricKeyData(privKey);

			IBufferedCipher c2;
			string cipherName = PgpUtilities.GetSymmetricCipherName((SymmetricKeyAlgorithmTag) plain[0]);
			string cName = cipherName;

			try
            {
                if (encData is SymmetricEncIntegrityPacket)
                {
					cName += "/CFB/NoPadding";
                }
                else
                {
					cName += "/OpenPGPCFB/NoPadding";
                }

				c2 = CipherUtilities.GetCipher(cName);
			}
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("exception creating cipher", e);
            }

			if (c2 == null)
				return encData.GetInputStream();

			try
            {
				KeyParameter key = ParameterUtilities.CreateKeyParameter(
					cipherName, plain, 1, plain.Length - 3);

				byte[] iv = new byte[c2.GetBlockSize()];

				c2.Init(false, new ParametersWithIV(key, iv));

                encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c2, null));

				if (encData is SymmetricEncIntegrityPacket)
                {
                    truncStream = new TruncatedStream(encStream);

					string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
					IDigest digest = DigestUtilities.GetDigest(digestName);

					encStream = new DigestStream(truncStream, digest, null);
                }

				if (Streams.ReadFully(encStream, iv, 0, iv.Length) < iv.Length)
					throw new EndOfStreamException("unexpected end of stream.");

				int v1 = encStream.ReadByte();
                int v2 = encStream.ReadByte();

				if (v1 < 0 || v2 < 0)
                    throw new EndOfStreamException("unexpected end of stream.");

				// Note: the oracle attack on the "quick check" bytes is deemed
				// a security risk for typical public key encryption usages,
				// therefore we do not perform the check.

//				bool repeatCheckPassed =
//					iv[iv.Length - 2] == (byte)v1
//					&&	iv[iv.Length - 1] == (byte)v2;
//
//				// Note: some versions of PGP appear to produce 0 for the extra
//				// bytes rather than repeating the two previous bytes
//				bool zeroesCheckPassed =
//					v1 == 0
//					&&	v2 == 0;
//
//				if (!repeatCheckPassed && !zeroesCheckPassed)
//				{
//					throw new PgpDataValidationException("quick check failed.");
//				}

				return encStream;
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception starting decryption", e);
            }
		}
        /// <summary>Return the decrypted data stream for the packet.</summary>
        public Stream GetDataStream(
            PgpPrivateKey privKey)
        {
            IBufferedCipher c1 = GetKeyCipher(keyData.Algorithm);

            try
            {
                c1.Init(false, privKey.Key);
            }
            catch (InvalidKeyException e)
            {
                throw new PgpException("error setting asymmetric cipher", e);
            }

            BigInteger[] keyD = keyData.GetEncSessionKey();

            if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt
                || keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
            {
                byte[] bi = keyD[0].ToByteArray();

                if (bi[0] == 0)
                {
                    c1.ProcessBytes(bi, 1, bi.Length - 1);
                }
                else
                {
                    c1.ProcessBytes(bi, 0, bi.Length);
                }
            }
            else
            {
                ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key;
                int size = (k.Parameters.P.BitLength + 7) / 8;

                byte[] bi = keyD[0].ToByteArray();

                int diff = bi.Length - size;
                if (diff >= 0)
                {
                    c1.ProcessBytes(bi, diff, size);
                }
                else
                {
                    byte[] zeros = new byte[-diff];
                    c1.ProcessBytes(zeros);
                    c1.ProcessBytes(bi);
                }

                bi = keyD[1].ToByteArray();

                diff = bi.Length - size;
                if (diff >= 0)
                {
                    c1.ProcessBytes(bi, diff, size);
                }
                else
                {
                    byte[] zeros = new byte[-diff];
                    c1.ProcessBytes(zeros);
                    c1.ProcessBytes(bi);
                }
            }

            byte[] plain;
            try
            {
                plain = c1.DoFinal();
            }
            catch (Exception e)
            {
                throw new PgpException("exception decrypting secret key", e);
            }

            if (!ConfirmCheckSum(plain))
            {
                throw new PgpKeyValidationException("key checksum failed");
            }

            IBufferedCipher c2;
            string cipherName = PgpUtilities.GetSymmetricCipherName((SymmetricKeyAlgorithmTag) plain[0]);
            string cName = cipherName;

            try
            {
                if (encData is SymmetricEncIntegrityPacket)
                {
                    cName += "/CFB/NoPadding";
                }
                else
                {
                    cName += "/OpenPGPCFB/NoPadding";
                }

                c2 = CipherUtilities.GetCipher(cName);
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("exception creating cipher", e);
            }

            if (c2 == null)
            {
                return encData.GetInputStream();
            }

            try
            {
                byte[] keyBytes = new byte[plain.Length - 3];
                Array.Copy(plain, 1, keyBytes, 0, keyBytes.Length);

                KeyParameter key = ParameterUtilities.CreateKeyParameter(
                    cipherName, keyBytes);

                byte[] iv = new byte[c2.GetBlockSize()];

                c2.Init(false, new ParametersWithIV(key, iv));

                encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c2, null));

                if (encData is SymmetricEncIntegrityPacket)
                {
                    truncStream = new TruncatedStream(encStream);
                    encStream = new DigestStream(truncStream,
                        DigestUtilities.GetDigest(PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1)), null);
                }

                for (int i = 0; i != iv.Length; i++)
                {
                    int ch = encStream.ReadByte();

                    if (ch < 0)
                    {
                        throw new EndOfStreamException("unexpected end of stream.");
                    }

                    iv[i] = (byte)ch;
                }

                int v1 = encStream.ReadByte();
                int v2 = encStream.ReadByte();

                if (v1 < 0 || v2 < 0)
                {
                    throw new EndOfStreamException("unexpected end of stream.");
                }

                // Note: the oracle attack on the "quick check" bytes is deemed
                // a security risk for typical public key encryption usages,
                // therefore we do not perform the check.

            //				bool repeatCheckPassed =
            //					iv[iv.Length - 2] == (byte)v1
            //					&&	iv[iv.Length - 1] == (byte)v2;
            //
            //				// Note: some versions of PGP appear to produce 0 for the extra
            //				// bytes rather than repeating the two previous bytes
            //				bool zeroesCheckPassed =
            //					v1 == 0
            //					&&	v2 == 0;
            //
            //				if (!repeatCheckPassed && !zeroesCheckPassed)
            //				{
            //					throw new PgpDataValidationException("quick check failed.");
            //				}

                return encStream;
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception starting decryption", e);
            }
        }
Exemple #9
0
 private static byte[] ComputeHash(object document)
 {
     var sha = new Sha256Digest();
     var stream = new DigestStream(new MemoryStream(), null, sha);
     using (var writer = new StreamWriter(stream))
     {
         string mementoToString = JsonConvert.SerializeObject(document);
         writer.Write(mementoToString);
     }
     byte[] buffer = new byte[sha.GetDigestSize()];
     sha.DoFinal(buffer, 0);
     return buffer;
 }