1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
//-----------------------------------------------------------------------
// <copyright file="SymbolHelper.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace System.Activities.Debugger.Symbol
{
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Runtime;
using System.Security;
using System.Security.Cryptography;
internal static class SymbolHelper
{
static readonly Guid Md5IdentifierGuid = new Guid("406ea660-64cf-4c82-b6f0-42d48172a799");
static readonly Guid Sha1IdentifierGuid = new Guid("ff1816ec-aa5e-4d10-87f7-6f4963833460");
public static Guid ChecksumProviderId
{
get
{
if (LocalAppContextSwitches.UseMD5ForWFDebugger)
{
return Md5IdentifierGuid;
}
else
{
return Sha1IdentifierGuid;
}
}
}
// This is the same Encode/Decode logic as the WCF FramingEncoder
public static int ReadEncodedInt32(BinaryReader reader)
{
int value = 0;
int bytesConsumed = 0;
while (true)
{
int next = reader.ReadByte();
value |= (next & 0x7F) << (bytesConsumed * 7);
bytesConsumed++;
if ((next & 0x80) == 0)
{
break;
}
}
return value;
}
// This is the same Encode/Decode logic as the WCF FramingEncoder
public static void WriteEncodedInt32(BinaryWriter writer, int value)
{
Fx.Assert(value >= 0, "Must be non-negative");
while ((value & 0xFFFFFF80) != 0)
{
writer.Write((byte)((value & 0x7F) | 0x80));
value >>= 7;
}
writer.Write((byte)value);
}
public static int GetEncodedSize(int value)
{
Fx.Assert(value >= 0, "Must be non-negative");
int count = 1;
while ((value & 0xFFFFFF80) != 0)
{
count++;
value >>= 7;
}
return count;
}
public static byte[] CalculateChecksum(string fileName)
{
Fx.Assert(!string.IsNullOrEmpty(fileName), "fileName should not be empty or null");
byte[] checksum;
try
{
using (StreamReader streamReader = new StreamReader(fileName))
{
using (HashAlgorithm hashAlgorithm = CreateHashProvider())
{
checksum = hashAlgorithm.ComputeHash(streamReader.BaseStream);
}
}
}
catch (IOException)
{
// DirectoryNotFoundException and FileNotFoundException are expected
checksum = null;
}
catch (UnauthorizedAccessException)
{
// UnauthorizedAccessException is expected
checksum = null;
}
catch (SecurityException)
{
// Must not have had enough permissions to access the file.
checksum = null;
}
return checksum;
}
[Fx.Tag.SecurityNote(Critical = "Used to get a string from checksum that is provided by the user/from a file.",
Safe = "We not exposing any critical data. Just converting the byte array to a hex string.")]
[SecuritySafeCritical]
public static string GetHexStringFromChecksum(byte[] checksum)
{
return checksum == null ? string.Empty : string.Join(string.Empty, checksum.Select(x => x.ToString("X2")).ToArray());
}
[Fx.Tag.SecurityNote(Critical = "Used to validate checksum that is provided by the user/from a file.",
Safe = "We not exposing any critical data. Just validating that the provided checksum meets the format for the checksums we produce.")]
[SecuritySafeCritical]
internal static bool ValidateChecksum(byte[] checksumToValidate)
{
// We are using MD5.ComputeHash, which will return a 16 byte array.
if (LocalAppContextSwitches.UseMD5ForWFDebugger)
{
return checksumToValidate.Length == 16;
}
else
{
return checksumToValidate.Length == 20;
}
}
[SuppressMessage("Microsoft.Cryptographic.Standard", "CA5350:MD5CannotBeUsed",
Justification = "Design has been approved. We are not using MD5 for any security or cryptography purposes but rather as a hash.")]
static HashAlgorithm CreateHashProvider()
{
if (LocalAppContextSwitches.UseMD5ForWFDebugger)
{
return new MD5CryptoServiceProvider();
}
else
{
return new SHA1CryptoServiceProvider();
}
}
}
}
|