Пример #1
0
        internal AssuredStreamHeader(AssuredStreamCreateArgs args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            args.VerifyArgs("args");

            _fileType = args.FileType;
            _hashType = args.HashType;

            if (args.StrongNameKey == null)
            {
                _fileHash      = new byte[QQnCryptoHelpers.GetHashBits(_hashType) / 8];
                _hashSignature = new byte[0];
            }
            else
            {
                _snk           = args.StrongNameKey;
                _fileHash      = new byte[_snk.HashLength];
                _hashSignature = new byte[_snk.SignatureLength];
                _hashType      = _snk.HashType;
            }
            _guid = args.NullGuid ? Guid.Empty : Guid.NewGuid();
        }
Пример #2
0
        internal static bool IsTagItemType(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (type == typeof(string) || type == typeof(ITagItem))
            {
                return(true);
            }

            if (type != _iTaskItem && (type.Name == "ITaskItem" && type.Namespace == "Microsoft.Build.Framework"))
            {
                if (_iTaskItem == null)
                {
                    // Never load the assembly ourselves, but allow nevertheless
                    AssemblyName name = new AssemblyName(type.Assembly.FullName);

                    if (QQnCryptoHelpers.HashString(name.GetPublicKeyToken()) == "b03f5f7f11d50a3a")
                    {
                        _iTaskItem = type;
                    }
                }
            }

            return(type == _iTaskItem);
        }
Пример #3
0
        public void TestSign()
        {
            Assert.That(QQnCryptoHelpers.CalculateFileHash(SnkFile, HashType.None), Is.EqualTo("dcd59a19afe007b2a7e706d100f8fcdeb4e4e1e9,type=SHA1,size=596"), "SHA256++Hash matches");
            Assert.That(QQnCryptoHelpers.CalculateFileHash(SnkFile, HashType.SHA256), Is.EqualTo("31a02f23fb06dc6326428843782c049d14e90fb14f74704909e6e6ba1a2592c0"), "SHA256 hash matches");
            Assert.That(QQnCryptoHelpers.CalculateFileHash(SnkFile, HashType.SHA1), Is.EqualTo("dcd59a19afe007b2a7e706d100f8fcdeb4e4e1e9"), "SHA1 hash matches");
            Assert.That(QQnCryptoHelpers.CalculateFileHash(SnkFile, HashType.MD5), Is.EqualTo("2b19ab067c03e05d55f62702c4a79864"), "MD5 hash matches");


            SignAndVerify(HashType.MD5);
            SignAndVerify(HashType.SHA1);
            SignAndVerify(HashType.SHA256);
            SignAndVerify(HashType.SHA512);
            SignAndVerify(HashType.SHA384);

            // RipeMD160 requires type, or it is validated against SHA1
            SignAndVerify(HashType.RipeMD160 | HashType.PlusType);

            string hash = QQnCryptoHelpers.CalculateFileHash(SnkFile, HashType.RipeMD160);

            Assert.That(QQnCryptoHelpers.VerifyFileHash(SnkFile, hash), Is.False);             // SHA1 hash != RIPEMD160 hash

            SignAndVerify(HashType.SHA1 | HashType.PlusSize);
            SignAndVerify(HashType.SHA1 | HashType.PlusType);
            SignAndVerify(HashType.SHA1 | HashType.PlusSize | HashType.PlusType);
        }
Пример #4
0
        /// <summary>
        /// Verifies the file.
        /// </summary>
        /// <param name="baseDirectory">The base directory.</param>
        /// <param name="verifyData">The verify data.</param>
        /// <param name="verificationMode">The verification mode.</param>
        /// <returns></returns>
        public static bool VerifyFile(string baseDirectory, IVerifiableFile verifyData, VerifyMode verificationMode)
        {
            if (string.IsNullOrEmpty(baseDirectory))
            {
                throw new ArgumentNullException("baseDirectory");
            }
            else if (verifyData == null)
            {
                throw new ArgumentNullException("verifyData");
            }

            string path = QQnPath.Combine(baseDirectory, verifyData.Filename);

            FileInfo fif = new FileInfo(path);

            if (!fif.Exists)
            {
                return(false);
            }

            if (verificationMode < VerifyMode.Time)
            {
                return(true);
            }

            bool hasTime    = verifyData.LastWriteTimeUtc.HasValue;
            bool timeFailed = hasTime && fif.LastWriteTimeUtc != verifyData.LastWriteTimeUtc.Value;

            if (timeFailed && verificationMode == VerifyMode.Time)
            {
                return(false);
            }

            if (verificationMode < VerifyMode.TimeSize)
            {
                return(true);
            }

            bool hasSize    = (verifyData.FileSize >= 0);
            bool sizeFailed = hasSize && fif.Length != verifyData.FileSize;

            if ((timeFailed || sizeFailed) && verificationMode == VerifyMode.TimeSize)
            {
                return(false);
            }

            if (verificationMode < VerifyMode.FileHash)
            {
                return(true);
            }

            if (!string.IsNullOrEmpty(verifyData.FileHash) && !QQnCryptoHelpers.VerifyFileHash(fif.FullName, verifyData.FileHash))
            {
                return(false);
            }

            return(true);
        }
Пример #5
0
        /// <summary>
        /// Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream.
        /// </summary>
        public override void Close()
        {
            if (_closed)
            {
                return;
            }

            _closed = true;
            if (!string.IsNullOrEmpty(_newHash) && _size != Length)
            {
                Debug.WriteLine(">>> Got invalid predefined hash");
                _hashOnClose = true;
            }


            if (_hashOnClose)
            {
                if (!_hashWhileWriting)
                {
                    if (_hashAlgorithm != null)
                    {
                        Hasher.TransformFinalBlock(_emptyBytes, 0, 0);
                        GC.KeepAlive(Hasher.Hash);
                    }

                    base.Position = 0;
                    byte[] buffer = new byte[16384];
                    int    nRead;

                    while (0 <= (nRead = base.Read(buffer, 0, buffer.Length)))
                    {
                        Hasher.TransformBlock(buffer, 0, nRead, null, 0);
                    }
                }

                Hasher.TransformFinalBlock(_emptyBytes, 0, 0);

                _newHash = QQnCryptoHelpers.HashString(Hasher.Hash, _hashType);
                _size    = Length;
            }
            base.Close();

            if (_updateOnClose)
            {
                _file.UpdateData(_newHash, _size, File.GetLastWriteTimeUtc(_file.FullName));
            }

            if (_hashAlgorithm != null)
            {
                _hashAlgorithm.Clear();                 // Disposes the hasher
                _hashAlgorithm = null;
            }
        }
Пример #6
0
        public void GuidTests()
        {
            Guid   baseGuid = new Guid("0D166EB6-69BC-47DB-A243-C31ECE55E715");
            string item     = "http://qqn.qqn.nl/qqn//qqn.qqn";

            Guid calcGuid = QQnCryptoHelpers.GuidFromHash(baseGuid, Encoding.UTF8.GetBytes(item));

            Assert.That(calcGuid, Is.EqualTo(new Guid("014C3195-DE6C-5A19-9563-163716A49EC6")), "Calculated guids are equal");

            calcGuid = QQnCryptoHelpers.GuidFromString(baseGuid, item);

            Assert.That(calcGuid, Is.EqualTo(new Guid("014C3195-DE6C-5A19-9563-163716A49EC6")), "Calculated guids are equal");
        }
Пример #7
0
        byte[] CalculateHash(Stream stream, bool create)
        {
            long pos = stream.Position;

            if (create)
            {
                _bodyLength = StreamLength(stream);
            }

            using (HashAlgorithm hasher = (_snk != null) ? _snk.CreateHasher() : QQnCryptoHelpers.CreateHashAlgorithm(_hashType))
            {
                long newPos = _hashPosition;

                if (stream.Position != newPos)
                {
                    stream.Position = newPos;
                }

                byte[] buffer;

                using (MemoryStream ms = new MemoryStream())                 // Use memorystream and writer to resolve endian-issues
                    using (QQnBinaryWriter bw = new QQnBinaryWriter(ms))
                    {
                        bw.Write(_guid.ToByteArray());
                        bw.Write(_bodyLength);

                        buffer = ms.ToArray();
                    }

                hasher.TransformBlock(buffer, 0, buffer.Length, null, 0);

                buffer = new byte[8192];

                int nRead;

                while (0 != (nRead = stream.Read(buffer, 0, buffer.Length)))
                {
                    hasher.TransformBlock(buffer, 0, nRead, null, 0);
                }

                hasher.TransformFinalBlock(buffer, 0, 0);

                if (stream.CanSeek)
                {
                    stream.Position = pos;
                }

                return(hasher.Hash);
            }
        }
Пример #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AssuredSubStream"/> class.
        /// </summary>
        /// <param name="parentStream">The parent stream.</param>
        /// <param name="verificationMode">The verification mode.</param>
        public AssuredSubStream(Stream parentStream, VerificationMode verificationMode)
            : base(parentStream, true)
        {
            AssuredStream signedParent = GetService <AssuredStream>();

            if (signedParent != null)
            {
                _snk      = signedParent.AssemblyStrongNameKey;
                _hashType = signedParent.HashType;
            }
            else
            {
                _hashType = HashType.SHA1;
            }

            _headerPosition = parentStream.Position;

            _streamHash    = new byte[QQnCryptoHelpers.GetHashBits(_hashType) / 8];
            _hashSignature = new byte[(_snk != null) ? _snk.SignatureLength : 0];

            if (parentStream.CanWrite && parentStream.CanSeek && parentStream.Position == parentStream.Length)
            {
                _updating = true;
                WriteHeader();
            }
            else
            {
                QQnBinaryReader br = new QQnBinaryReader(BaseStream);
                _streamHash    = br.ReadBytes(_streamHash.Length);
                _hashSignature = br.ReadBytes(_hashSignature.Length);
                _hashLength    = br.ReadInt64();
                _hashPosition  = BaseStream.Position;

                if (verificationMode != VerificationMode.None)
                {
                    if (_snk != null && !_snk.VerifyHash(_streamHash, _hashSignature))
                    {
                        throw new CryptographicException("Stream hash verification failed");
                    }
                }

                if (verificationMode == VerificationMode.Full)
                {
                    if (!VerifyHash())
                    {
                        throw new CryptographicException("Invalid hash value");
                    }
                }
            }
        }
Пример #9
0
        /// <summary>
        /// Checks whether the two verifiers verify the same file
        /// </summary>
        /// <param name="one">The one.</param>
        /// <param name="other">The other.</param>
        /// <returns></returns>
        public static bool AreEqualVerifiers(IVerifiableFile one, IVerifiableFile other)
        {
            if (one == null)
            {
                throw new ArgumentNullException("one");
            }
            else if (other == null)
            {
                throw new ArgumentNullException("other");
            }

            if ((one.FileHash != null) && (other.FileHash != null))
            {
                // Compare hashes without size
                if (!string.Equals(QQnCryptoHelpers.NormalizeHashValue(one.FileHash, true), QQnCryptoHelpers.NormalizeHashValue(other.FileHash, true)))
                {
                    return(false);
                }
            }

            long oneSize   = one.FileSize;
            long otherSize = other.FileSize;

            // Get sizes from hash if they are not available directly
            if ((oneSize < 0) && one.FileHash != null)
            {
                oneSize = QQnCryptoHelpers.GetSizeFromHash(one.FileHash);
            }

            if ((otherSize < 0) && other.FileHash != null)
            {
                otherSize = QQnCryptoHelpers.GetSizeFromHash(other.FileHash);
            }

            if ((oneSize >= 0) && (otherSize >= 0) && (oneSize != otherSize))
            {
                return(false);
            }

            if (one.LastWriteTimeUtc.HasValue && other.LastWriteTimeUtc.HasValue && one.LastWriteTimeUtc.Value != other.LastWriteTimeUtc.Value)
            {
                return(false);
            }

            return(true);
        }
Пример #10
0
        byte[] CalculateHash(bool create)
        {
            if (create)
            {
                _hashLength = Length;
            }

            long oldPos = Position;

            Position = 0;
            using (HashAlgorithm hasher = QQnCryptoHelpers.CreateHashAlgorithm(_hashType))
            {
                byte[] buffer;
                using (MemoryStream ms = new MemoryStream(16))                 // Use memorystream and writer to resolve endian-issues
                    using (QQnBinaryWriter bw = new QQnBinaryWriter(ms))
                    {
                        bw.Write(_hashLength);
                        buffer = ms.ToArray();
                    }

                hasher.TransformBlock(buffer, 0, buffer.Length, null, 0);

                buffer = new byte[8192];

                int nRead;

                while (0 != (nRead = Read(buffer, 0, buffer.Length)))
                {
                    hasher.TransformBlock(buffer, 0, nRead, null, 0);
                }

                hasher.TransformFinalBlock(buffer, 0, 0);

                if (CanSeek)
                {
                    Position = oldPos;
                }

                return(hasher.Hash);
            }
        }
Пример #11
0
        /// <summary>
        /// Updates the file.
        /// </summary>
        /// <param name="baseDirectory">The base directory.</param>
        /// <param name="verifyData">The verify data.</param>
        /// <param name="hashType">Type of the hash.</param>
        public static void UpdateFile(string baseDirectory, IUpdatableVerifiableFile verifyData, HashType hashType)
        {
            if (string.IsNullOrEmpty(baseDirectory))
            {
                throw new ArgumentNullException("baseDirectory");
            }
            else if (verifyData == null)
            {
                throw new ArgumentNullException("verifyData");
            }

            FileInfo fif = new FileInfo(QQnPath.Combine(baseDirectory, verifyData.Filename));

            if (!fif.Exists)
            {
                return;
            }

            long     size = fif.Length;
            string   hash = QQnCryptoHelpers.CalculateFileHash(fif.FullName, hashType);
            DateTime dt   = fif.LastWriteTimeUtc;

            verifyData.UpdateVerifyData(hash, size, dt);
        }
Пример #12
0
        void SignAndVerify(HashType hashType)
        {
            string hash = QQnCryptoHelpers.CalculateFileHash(SnkFile, hashType);

            Assert.That(QQnCryptoHelpers.VerifyFileHash(SnkFile, hash), Is.True, "Hash of type {0} ok", hashType);
        }
Пример #13
0
        public void TestTokens()
        {
            StrongNameKey snkIn = StrongNameKey.LoadFrom(SnkFile);

            Assert.That(snkIn.PublicKeyToken, Is.EqualTo(QQnCryptoHelpers.HashString(typeof(QQnCryptoHelpers).Assembly.GetName().GetPublicKeyToken())), "Our public-token api matches the .Net one");
        }