SHOW:
|
|
- or go back to the newest paste.
| 1 | Add-Type -TypeDefinition @" | |
| 2 | // Copyright (c) Damien Guard. All rights reserved. | |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. | |
| 4 | // You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | |
| 5 | // Originally published at http://damieng.com/blog/2006/08/08/calculating_crc32_in_c_and_net | |
| 6 | // JaCk sourced it from: https://pastebin.com/s7eJQJk5 | |
| 7 | ||
| 8 | using System; | |
| 9 | using System.Collections.Generic; | |
| 10 | using System.Security.Cryptography; | |
| 11 | ||
| 12 | /// <summary> | |
| 13 | /// Implements a 32-bit CRC hash algorithm compatible with Zip etc. | |
| 14 | /// </summary> | |
| 15 | /// <remarks> | |
| 16 | /// Crc32 should only be used for backward compatibility with older file formats | |
| 17 | /// and algorithms. It is not secure enough for new applications. | |
| 18 | /// If you need to call multiple times for the same data either use the HashAlgorithm | |
| 19 | /// interface or remember that the result of one Compute call needs to be ~ (XOR) before | |
| 20 | /// being passed in as the seed for the next Compute call. | |
| 21 | /// </remarks> | |
| 22 | public sealed class Crc32 : HashAlgorithm | |
| 23 | {
| |
| 24 | public const UInt32 DefaultPolynomial = 0xedb88320u; | |
| 25 | public const UInt32 DefaultSeed = 0xffffffffu; | |
| 26 | ||
| 27 | static UInt32[] defaultTable; | |
| 28 | ||
| 29 | readonly UInt32 seed; | |
| 30 | readonly UInt32[] table; | |
| 31 | UInt32 hash; | |
| 32 | ||
| 33 | public Crc32() | |
| 34 | : this(DefaultPolynomial, DefaultSeed) | |
| 35 | {
| |
| 36 | } | |
| 37 | ||
| 38 | public Crc32(UInt32 polynomial, UInt32 seed) | |
| 39 | {
| |
| 40 | table = InitializeTable(polynomial); | |
| 41 | this.seed = hash = seed; | |
| 42 | } | |
| 43 | ||
| 44 | public override void Initialize() | |
| 45 | {
| |
| 46 | hash = seed; | |
| 47 | } | |
| 48 | ||
| 49 | protected override void HashCore(byte[] array, int ibStart, int cbSize) | |
| 50 | {
| |
| 51 | hash = CalculateHash(table, hash, array, ibStart, cbSize); | |
| 52 | } | |
| 53 | ||
| 54 | protected override byte[] HashFinal() | |
| 55 | {
| |
| 56 | var hashBuffer = UInt32ToBigEndianBytes(~hash); | |
| 57 | HashValue = hashBuffer; | |
| 58 | return hashBuffer; | |
| 59 | } | |
| 60 | ||
| 61 | public override int HashSize { get { return 32; } }
| |
| 62 | ||
| 63 | public static UInt32 Compute(byte[] buffer) | |
| 64 | {
| |
| 65 | return Compute(DefaultSeed, buffer); | |
| 66 | } | |
| 67 | ||
| 68 | public static UInt32 Compute(UInt32 seed, byte[] buffer) | |
| 69 | {
| |
| 70 | return Compute(DefaultPolynomial, seed, buffer); | |
| 71 | } | |
| 72 | ||
| 73 | public static UInt32 Compute(UInt32 polynomial, UInt32 seed, byte[] buffer) | |
| 74 | {
| |
| 75 | return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length); | |
| 76 | } | |
| 77 | ||
| 78 | static UInt32[] InitializeTable(UInt32 polynomial) | |
| 79 | {
| |
| 80 | if (polynomial == DefaultPolynomial && defaultTable != null) | |
| 81 | return defaultTable; | |
| 82 | ||
| 83 | var createTable = new UInt32[256]; | |
| 84 | for (var i = 0; i < 256; i++) | |
| 85 | {
| |
| 86 | var entry = (UInt32)i; | |
| 87 | for (var j = 0; j < 8; j++) | |
| 88 | if ((entry & 1) == 1) | |
| 89 | entry = (entry >> 1) ^ polynomial; | |
| 90 | else | |
| 91 | entry = entry >> 1; | |
| 92 | createTable[i] = entry; | |
| 93 | } | |
| 94 | ||
| 95 | if (polynomial == DefaultPolynomial) | |
| 96 | defaultTable = createTable; | |
| 97 | ||
| 98 | return createTable; | |
| 99 | } | |
| 100 | ||
| 101 | static UInt32 CalculateHash(UInt32[] table, UInt32 seed, IList<byte> buffer, int start, int size) | |
| 102 | {
| |
| 103 | var crc = seed; | |
| 104 | for (var i = start; i < size - start; i++) | |
| 105 | crc = (crc >> 8) ^ table[buffer[i] ^ crc & 0xff]; | |
| 106 | return crc; | |
| 107 | } | |
| 108 | ||
| 109 | static byte[] UInt32ToBigEndianBytes(UInt32 uint32) | |
| 110 | {
| |
| 111 | var result = BitConverter.GetBytes(uint32); | |
| 112 | ||
| 113 | if (BitConverter.IsLittleEndian) | |
| 114 | Array.Reverse(result); | |
| 115 | ||
| 116 | return result; | |
| 117 | } | |
| 118 | } | |
| 119 | "@ -PassThru | Out-Null | |
| 120 | ||
| 121 | Function Get-Crc32 | |
| 122 | {
| |
| 123 | Param ( | |
| 124 | [Parameter(Mandatory=$true)][String]$String | |
| 125 | ) | |
| 126 | $crc32 = New-Object Crc32 | |
| 127 | $encoding = [System.Text.Encoding]::UTF8 | |
| 128 | ||
| 129 | $bytes = $encoding.GetBytes($String) | |
| 130 | ||
| 131 | $hash = [String]::Empty | |
| 132 | foreach ($byte in $crc32.ComputeHash($bytes)) | |
| 133 | {
| |
| 134 | $hash += $byte.toString('x2').toLower()
| |
| 135 | } | |
| 136 | ||
| 137 | $hash | |
| 138 | } |