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(); }
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); }
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); }
/// <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); }
/// <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; } }
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"); }
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); } }
/// <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"); } } } }
/// <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); }
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); } }
/// <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); }
void SignAndVerify(HashType hashType) { string hash = QQnCryptoHelpers.CalculateFileHash(SnkFile, hashType); Assert.That(QQnCryptoHelpers.VerifyFileHash(SnkFile, hash), Is.True, "Hash of type {0} ok", hashType); }
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"); }