How to create an arbitrary list in SQL. Its a little easier said than done. Heres a code snippet which will do just that. The biggest power of this, is running queries to figure out what kind of ranges do not have any data. For example, consider a table of values between 1 and 10000. If someone were to ask which unique set of numbers existed in the table, that would be pretty easy. But if someone were to ask which set of number did not exist in the table, that query would be pretty tough. You have nothing to join against.

                            
DECLARE @lowInclusive  INT = 3
DECLARE @highInclusive INT = 55

-- Declare a common table expression
;WITH generator AS
(
    -- In the base case, just select our first number as a row
    SELECT
        number
    FROM (VALUES(@lowInclusive)) AS base(number)

    UNION ALL

    -- Now select recursively from the common table until we reach our high number
    SELECT
        number + 1
    FROM generator
    WHERE number < @highInclusive
)
SELECT * FROM generator

                            
                        
There you have it. A row list of numbers. You can expand this do work with things like dates as well.

                            
DECLARE @lowInclusive  Date = GETUTCDATE()
DECLARE @highInclusive Date = DATEADD(DAY, 30, @lowInclusive)

-- Declare a common table expression
;WITH generator AS
(
    -- In the base case, just select our first number as a row
    SELECT
        d
    FROM (VALUES(@lowInclusive)) AS base(d)

    UNION ALL

    -- Now select recursively from the common table until we reach our high number
    SELECT
        DATEADD(DAY, 1, d)
    FROM generator
    WHERE d < @highInclusive
)
SELECT * FROM generator

                            
                        
There you have it. The result ends up looking like this

day
2017-08-12
2017-08-13
2017-08-14
2017-08-15
2017-08-16
2017-08-17
2017-08-18
2017-08-19
2017-08-20
2017-08-21
2017-08-22
2017-08-23
2017-08-24
2017-08-25
2017-08-26
2017-08-27
2017-08-28
2017-08-29
2017-08-30
2017-08-31
2017-09-01
2017-09-02
2017-09-03
2017-09-04
2017-09-05
2017-09-06
2017-09-07
2017-09-08
2017-09-09
2017-09-10
2017-09-11

And now you can easily join to figure out which days of the month someone forgot to pay their bills, or whatever.




Some messy C# code.

Mar09.17 07AM

Ever been asked FizzBuzz in a programming interview, and thought to yourself, what could I do here that would really throw them off? Well, this. Do this.

                            
private static void FizzBuzz1()
{              
	// Declare all of our variables right here at the top.
	int i, i2;
	string buff;
	Action<string> fb = null;
	goto assignVars;
	loop:
	{
		if (0 == i2 % 3)
		goto dofizz;
		if (0 == i2 % 5)
		goto dobuzz;
		goto donumber;
	}
	endoftheloop:
	if (i --> 0 && (i2 = 100 - i) > 0)
	goto loop;
	goto end;
	dofizz:
	buff += "fizz";
	if (0 == i2 % 5)
	goto dobuzz;
	goto writer;
	dobuzz:
	buff += "buzz";
	goto writer;
	donumber:
	buff += i2;
	writer:
	fb(buff + Environment.NewLine);
	goto justBuff;
	// Do this safely at the end of the function.
	assignVars:
	i = 100;
	fb = Console.Write;
	justBuff:
	buff = string.Empty;
	goto endoftheloop;
	end: ;
}
                            
                        
Nobody can be tooooo mad, since it really is a completely working fizzbuzz. Some may question who taught you that goto works in c#, and why you dont seem to know how to use a for-loop. Some may even question why you assigned Console.Write to an action, or why you didn't just use Console.WriteLine. All good questions. Seems like you would have a lot to talk about during your interview.

Theres nothing like a single method chain which does all of Fizz Buzz. So here's some awesome.

                            
private static void FizzBuzz2()
{
  Console.WriteLine(
    string.Join(
      Environment.NewLine,
      Enumerable.Range(1, 100)
        .Select(
          i =>
            string.Join(
              string.Empty,
              i % 3 == 0 ? "fizz" : null,
              i % 5 == 0 ? "buzz" : null,
              !(i % 5 == 0 || i % 3 == 0) ? $"{i}" : null))));
}
                            
                        



This post is to check if if images work! Will see what happens. This may be a mess.

If this picture isn't currently ruining the entire page, then this is a success.




Here is one to get the people going. Have you ever had an issue, where you tried to mount too many disks on your machine at one time, and ran out of driver letters? Well have no fear. It is a totally normal problem. Instead of mounting to drive letters... of which there are only 26. We can add access paths to partitions on the disk. You know what the best news is? The limit on access paths is totally crazy. I have once mounted 50 disks at the same time, and everything still seemed to work.

So here is the rub. This example is going to use a bunch of powershell cmdlets. But all of these are just wrappers around the root\microsoft\windows\storage CIM namespace. We could do this the badass way using only CIM, but it would be much longer, and I need something to write about tomorrow.

Anyway, this is what the code looks like.

                            
#
# Mount a virtual hard disk to a folder
#
function Mount-VHDToFolder
{
    [CmdLetBinding()]
    param
    (
        [Parameter(Mandatory=$true)][String]$Image,
        [Parameter(Mandatory=$true)][String]$MountFolder
    )
    process
    {
        try
        {
            # Gets a mounted disk image
            $mountedDisk = Mount-DiskImage -ImagePath $Image -NoDriveLetter -PassThru -ErrorAction Stop | Get-DiskImage
        }
        catch
        {
            Write-Error "Failed to mount disk"
            return
        }

        # Get all of the partitions
        $partitions = Get-Partition -DiskNumber $mountedDisk.Number

        foreach($partition in $partitions)
        {
            $partFolder = Join-Path $MountFolder $partition.PartitionNumber

            # Clean up this folder if it exists
            if(Test-Path $partFolder)
            {
                rmdir -Force $partFolder
            }

            # Make the new folder
            mkdir $partFolder | Out-Null

            try
            {
                # Add the access path for the disk
                Add-PartitionAccessPath -InputObject $partition -AccessPath $partFolder -ErrorAction Stop
            }
            catch
            {
                Write-Warning "Could not add access path '$($partFolder)' for partition '$($partition.PartitionNumber)'"
            }
        }
    }
}
                            
                        
This is going to create a folder for each partition number in the mount folder which you provide. It will try to add an access path for each partition. FYI, the reason I check if the folder exists, and delete it, is because AddAccessPath will fail if there is a broken symbolic link on the folder. AKA, you dismounted a disk which was using that folder as an access path without removing the access path first.

And there you have it! It is pretty simple really. Mounting the disk image gives us a MSFT_Disk cim object. We can use that disk to get all of the related MSFT_Partition cim objects. The MSFT_Partition object has a method called "AddAccessPath". Powershell wraps all of this stuff up for us super nicely so we won't need to mess with it.




So here is the solution to an annoying one. Have you ever made an asp.net website and tried to make custom error pages? So here is the issue. I could not, for the longest time, figure out how to make my custom error pages actually show up for the user. Seriously, everything worked fantastic, until my HTTP response was anything other than 200. My solution was to return a "soft" 404 page. Which web crawlers really hate.

Soft Error - When you catch the error on the server, and return an error page with a success error code. For example a user browses to a link on your site which does not exist, causing a 404. You serve up a 404 page, but with a "200 OK" response code. From a user's perspective this is fine, but bots have no idea what is going on.

To be entirely honest, I made up most of that definition. Wikipedia refers to it as a "phony 404 error". Realistically you can do the same thing for any type of error on the server side. Actually, you can throw response codes out the window and return whatever crap you want all the time. Do it... Return a 500 for every single page. Users will never notice, but bots will lose their minds. (Actually you'll just never make it anywhere near the top on any search engine).

Ok So let's get back to the point here. Instead of a "Soft Error", you should always return the proper error code. IIS doesn't like to make this easy for you by default, so here is what you need to configure to make sure everything works properly.

                            
  <system.webServer>
    <httpErrors existingResponse="PassThrough"></httpErrors>
  </system.webServer>
                            
                        
Just stick this in the System.webServer section in your web.config. "existingResponse=PassThrough" pretty much means that you are going to take matters into your own hands when it comes to errors. If an error response comes down the pipe (aka: http code >= 400) then IIS will leave the message untouched if a response exists.

Hope this helps. My ones of users have been consistently complaining about poor error handling issues, so I dedicated my night (after this glorious Donald vs. Hillary debate) to fixing the issue. Thanks for your feedback Daniel.




So here we are again. A long adventure to get some food has been completed. The TV blaring Season 5 of New Girl. I think to myself, you know what would go really well with this Shawarma? If I could finally read an IPv6 address without looking like an idiot. So here goes. IPv4 is simple, 32 bits of easy to understand goodness. Every single IPv4 address is made up of 4 bytes. For example "192.168.1.1". There is no shorthand either, that is the address, that's it. There is no better way to write it. Ok, so now that that is out of the picture, what is IPv6.

IPv6 is 128 bits of a little bit more confusing. Well actually, it's not the address that is confusing, it's the notation. When you see IPv6, a lot of times you see things like "::1" and "FE80::1". What does that even mean. How is that 128 bits. How will we ever know. So the secret is in the "::", which is pretty much just shorthand for "a lot of zeros go here".

For example: if we take the address "::1", it actually expands out to "0000:0000:0000:0000:0000:0000:0000:0001". Literally just means fill in this space with zeros. Another example: "FE80::1" becomes "FE80:0000:0000:0000:0000:0000:0000:0001". Just FYI, you are only allowed to use the "::" once, otherwise addresses would be unreadable. ("::1::") So before anything, here is a function to automate that, because it drives me nuts.

                            
#
# Expand an IPv6 address. For example ::1 becomes 0000:0000:0000:0000:0000:0000:0000:0001
#
function Expand-IPV6
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true, 
                   Position = 0,
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true)][String]$IPv6
    )
    process
    {
        $count = 0
        $loc = -1

        # Count the number of colons, and keep track of the double colon
        for($i = 0; $i -lt $IPv6.Length; $i++) 
        { 
            if($IPv6[$i] -eq ':') 
            {
                $count++
                if(($i - 1) -ge 0 -and $IPv6[$i-1] -eq ':')
                {
                    $loc = $i
                }
            }
        }

        # If we didnt find a double colon and the count isn't 7, then throw an exception
        if($loc -lt 0 -and $count -ne 7)
        {
            throw "Invalid IPv6 Address"
        }

        # Add in any missing colons if we had a double
        $cleaned = $IPv6
        if($count -lt 7)
        {
            $cleaned = $IPv6.Substring(0, $loc) + (':'*(7-$count)) + $IPv6.Substring($loc)
        }

        # Parse current values in fill in new IP with hex numbers padded to 4 digits
        $result = @()
        foreach($splt in $cleaned -split ':')
        {
            $val = 0
            $r = [int]::TryParse($splt, [System.Globalization.NumberStyles]::HexNumber, [System.Globalization.CultureInfo]::InvariantCulture, [ref]$val)
            $result += ('{0:X4}' -f $val)
        }

        return $result -join ':'
    }
}
                            
                        
So this does the expansions work for us, because it’s a pain in the butt to deal with these addresses in their short form. Also, I know the code is gross and I apologize for that, but there is more to come. Ok, so now, what happens if we have an IPv4 address and we need to turn it into IPv6. Boom, its easy. The last 32 bits of the IPv6 address are equal to our IPv4 address, and the 16 bits preceding those are all set to 1. Easy enough! That means, the IP address 1.1.1.1 would turn into "::FFFF:0101:0101" or "0000:0000:0000:0000:0000:FFFF:0101:0101" in full form. So how do we make that happen?

                            
# Map an IPv4 address to IPv6
function Map-IPv4ToIPv6
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true, 
            Position = 0,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true)][String]$IPv4
    )
    process
    {
        # Split on the dots
        $split = $IPv4 -split '\.'
        if($split.Length -ne 4)
        {
            throw 'Not a valid IPv4 Address'
        }

        # Parse into numbers
        $vals = @()
        foreach($v in $split)
        {
            $vals += [int]::Parse($v)
        }

        # Return as shorthand ipv6
        return "::FFFF:{0:X2}{1:X2}:{2:X2}{3:X2}" -f $vals
    }
}
                            
                        
BOOM, mission accomplished. Hopefully (it worked in a few tests). Also, for completeness, here is a function which turns an IPv4 address which is represented in IPv6 back into an IPv4 address.

                            
#
# Transforms an IPv4 address which is represented in IPv6 back into IPv4
#
function Map-IPv6ToIPv4
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true, 
            Position = 0,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true)][String]$IPv6
    )
    process
    {
        # Get the expanded form
        $expanded = Expand-IPV6 $IPv6
        $split = $expanded.Split(':')

        # Make sure this is valid...
        $is4MappedTo6 = $split[5] -match 'FFFF'
        if(-not $is4MappedTo6)
        {
            throw 'This is not an IPv4 Address mapped to IPv6'
        }

        # Parse each byte as an integer
        $addr = @()
        for($i = 0; $i -lt 8; $i+=2)
        {
            $addr += [int]::Parse(($split[6 + [math]::Floor(($i / 4))][($i % 4)..(($i%4)+1)] -join ''), [System.Globalization.NumberStyles]::HexNumber)
        }

        return $addr -join '.'
    }
}
                            
                        
The classes built in to handle IP addresses are definitely much smarter, and the way to go. But this was a sad attempt at a way to do it in Powershell!




SHA1 in F#

Sep25.16 12AM

So, Season 5 of New Girl just came out on Netflix. I think you know where this is going, but effectively I sat in the Lovesac and watched TV all day. To feel a little bit better, I thought I should exercise my fingers a bit. Anyway here goes, back by popular demand, an F# implementation of SHA1. Now, before you look at my crap code and start asking questions. This is pretty much my first time ever using F#. Anyway, it compiles, and I've tested it a few times, so it seems 100% ready to ship.

                            
// Converts an ascii string into a byte sequence
let getBytes (input: string) = seq {for c in input -> (byte)c}

// Get a uint32 from a sequence of 4 bytes in big endian
let bytesToUi (input: seq<byte>) = 
    let i = ref 3

    // My decrementor function because I didnt realize value assignment don't return a value
    let dec value =
        let t = !value
        value := (!value - 1)
        t
    // Fold the 4 bytes into a uint
    Seq.fold (fun (acc : uint32) (b : byte) -> acc ||| (uint32(b) <<< (dec i) * 8)) 0u input

// Rotate left
let rotl (input: uint32) (amount) =
    (input <<< amount) ||| (input >>> (32 - amount))

// Runs SHA1 on a string
let sha1 (input: string) =
    // Get length of input in bytes
    let messageLen = uint32(input.Length)

    // Get length of input in bits
    let bitlen = uint64(8u * messageLen)

    // Get the amount we need to pad. Include the bit (0x80) we append to the message and the ulong at the end of the message for length
    let padlen = 
        match ((messageLen + 9u) % 64u) with
        | 0u -> 0
        | _ -> int(64u - ((messageLen + 9u) % 64u))

    // Append the bit to the end of the message
    let asciibytes = Seq.append (getBytes(input)) (Seq.singleton 0x80uy)

    // Pad with 0s. Assume the length is not going to be larger than uint32, so set the highest order 4 bytes to zero as well
    let asciibytes = Seq.append asciibytes (seq {for i in 1.. (padlen+4) -> 0uy})

    // Append 64 bits of message length
    let messageBytes = Seq.append asciibytes (seq {for i in (List.rev [0..7]) -> ((byte)(bitlen >>> (i * 8)))})

    // Constants
    let mutable h0 = 0x67452301u
    let mutable h1 = 0xEFCDAB89u
    let mutable h2 = 0x98BADCFEu
    let mutable h3 = 0x10325476u
    let mutable h4 = 0xC3D2E1F0u

    // Get the total message length
    let totalBytes = Seq.length messageBytes

    // For each 64 byte chunk
    for chunk = 0 to ((totalBytes / 64)-1) do
        let w = [| for i in 1 .. 80 -> 0u|]

        // Populate the array
        for i = 0 to 15 do
            w.[i] <- bytesToUi (Seq.take 4 (Seq.skip (i*4 + chunk * 64) messageBytes))
        for i = 16 to 79 do
            w.[i] <- rotl ((w.[i-3]) ^^^ (w.[i-8]) ^^^ (w.[i-14]) ^^^ (w.[i-16])) 1

        // Set up the locals
        let mutable a, b, c, d, e = h0, h1, h2, h3, h4
        let mutable k = 0u
        let mutable f = 0u

        for i in 0 .. 79 do
            let round = match i with
                        | m when m < 20 -> (0x5A827999u, ((b &&& c) ||| ((~~~b) &&& d)))
                        | m when m < 40 -> (0x6ED9EBA1u, (b ^^^ c ^^^ d))
                        | m when m < 60 -> (0x8F1BBCDCu, ((b &&& c) ||| (b &&& d) ||| (c &&& d)))
                        | _ -> (0xCA62C1D6u, (b ^^^ c ^^^ d))
            let temp = (rotl a 5) + (snd round) + e + (fst round) + w.[i]
            e <- d
            d <- c
            c <- rotl b 30
            b <- a
            a <- temp

        h0 <- h0 + a
        h1 <- h1 + b
        h2 <- h2 + c
        h3 <- h3 + d
        h4 <- h4 + e

    [h0; h1; h2; h3; h4]
                            
                        



Every once in a while, you end up on a friend's computer and you think to yourself, what is the most annoying thing I can do RIGHT NOW. Well don't even worry, here is a super quick way to make some gigantic files. Of course, it starts with opening up PowerShell. (You can do the same thing on a Unix machine with 'cat'). Ok let's do it.

                            
'a' * 1000 > temp.txt
Get-Content temp.txt >> temp.txt
                            
                        
  1. Writes the letter 'a' to a file named temp.txt 1000 times.
  2. Reads temp.txt line by line, and appends it to the end of temp.txt

Pretty simple right!? Just a never ending loop of file writing. You can event do it in a single line.

                            
'a' * 1000 > temp.txt; gc temp.txt >> temp.txt
                            
                        
The real question is, how fast does this baby go. So here we go, a test which lets this run for 30 seconds, then kills it.

                            
$job = Start-Job -ScriptBlock {'a' * 1000 > temp.txt; Get-Content temp.txt >> temp.txt}
Wait-Job -Job $job -Timeout 30
Stop-Job -Job $job
                            
                        
This made me a nice 1.4GB text file. Also tried for 120 seconds, and ended up with a 5.2GB file. So there you have it. Fun time with files.




Here is a quick one. I couldn't find a great way to find the amount of free space which exists on a disk with powershell. I am sure there is a good option, but anway, here is a great solution with uses P/Invoke. This will uses the kernel32 function: GetDiskFreeSpaceEx to figure out how much free space is on a drive. It seems to work pretty well. One catch, P/Invoke in powershell is weird. You pretty much need to go compile the C#.

                            
#
# Gets the amount of free disk space.
#
function Get-DiskFreeSpace
{
    [CmdLetBinding()]
    param
    (
        [Parameter(Mandatory = $false)]$Directory = $pwd
    )
    process
    {
        # Name of the P/Invoke we are going to use
        $name = 'GetDiskFreeSpaceEx'

        # The dll the funciton is in
        $dll = 'kernel32.dll'

        # The P/Invoke function definition
        $def = "[DllImport(`"$dll`")]
        public static extern bool $name(string lpDirectoryName,
           out ulong lpFreeBytesAvailable, 
           out ulong lpTotalNumberOfBytes, 
           out ulong lpTotalNumberOfFreeBytes);"

        # First try to see if this already exists
        $type = 'Microsoft.PowerShell.Commands.AddType.AutoGeneratedTypes.GetStorageFreeType' -as [type]
        
        # If not, new up a runtime type with this function definition
        if(-not $type)
        {
            $type = Add-Type -MemberDefinition $def -Name "GetStorageFreeType" -PassThru
        }

        $freeBytes = [uint64]0
        $totalBytes = [uint64]0
        $totalFreeBytes = [uint64]0

        # Do the P/Invoke
        $res = $type::GetDiskFreeSpaceEx($Directory, [ref] $freeBytes, [ref] $totalBytes, [ref] $totalFreeBytes)

        # Get the total free bytes
        return $totalFreeBytes
    }
}
                            
                        



Have you ever thought to yourself, "How does a deprecated standard like SHA1 work, and how could it be implemented in powershell?". Well look no further. Actually, it was a litte harder than it seems, since powershell REALLY loves signed numbers. Lets take for example: 0xFFFFFFFF, which one would assume is ?equal to 4294967295?. Well.. Check out this simple line of code.

                            
#This wont throw an exception right?
[uint32]0xFFFFFFFF
                            
                        
Well, in powershell this just throws an exception. You know why!? Because under the hood, PShelly goes OH "0xFFFFFFFF", that's 32 bits. Let me stick it in a 32 bit signed integer. But wait... "0xFFFFFFFF" is just 32 1s. But oh crap, in 2s complement, that's -1. So in powershell 0xFFFFFFFF == -1. So now its pretty clear why the above code throws an exception, there is no unsigned value to represent -1. Seriously, just go type "0xFFFFFFFF" into powershell. So.. because of that, everything here has to be done in a 64 bit integer.

                            
#
# Implemenation of SHA1
#
function SHA1
{
    [CmdLetBinding()]
    param
    (
        [Parameter(Mandatory = $false, Position=1)][string]$Str
    )
    process
    {
        #
        # Truncate a value to UInt32
        #
        function TUI
        {
            param($val)
            process
            {
                [uint64]($val -band (((-bnot [uint64]0)) -shr 32))
            }
        }

        #
        # Get a 32 bit value from a byte array
        #
        function GetBigEndianUInt
        {
            param
            (
                [byte[]]$bytes,
                [int]$index
            )
            process
            {
                return ([uint64]$bytes[$index] -shl 24) -bor ([uint64]$bytes[$index+1] -shl 16) -bor ([uint64]$bytes[$index+2] -shl 8) -bor ([uint64]$bytes[$index+3])
            }
        }

        #
        # Left rotate
        #
        function LeftRotate
        {
            param
            (
                [uint64]$val,
                [int]$amount
            )
            process
            {
                $res = TUI ([uint64]$val -shr (32 - $amount))
                $res = $res -bor ($val -shl $amount)
                return TUI $res
            }
        }

        # Initialize constants
        $h0 = TUI 0x67452301
        $h1 = TUI 0xEFCDAB89
        $h2 = TUI 0x98BADCFE
        $h3 = TUI 0x10325476
        $h4 = TUI 0xC3D2E1F0
        
        # Get the message bytes
        $message = [System.Text.ASCIIEncoding]::ASCII.GetBytes($Str)

        # Get the length in bytes which we need. Message length + 0x80 + (64bit message len)
        $len = ($message.Length + 9)
        
        # Get the padded length of our our byte array
        if($len % 64 -ne 0){
            $len += (64 - ($len % 64))
        }

        # Copy the bytes in the message to our byte array
        $bytes = ([byte[]]0 * $len)
        for($i = 0; $i -lt $message.Length; $i++){
            $bytes[$i] = [byte]$message[$i]
        }

        # Pad the message with 1000 0000
        $bytes[$i] = 128

        # The message length in bits
        $bitLen = $message.Length * 8

        # Set the last [uint64] as the messsage length. (We only do 32 bits)
        $bytes[$len-1] = [byte]($bitLen -band 0xFF)
        $bytes[$len-2] = [byte](($bitLen -shr 8) -band 0xFF)
        $bytes[$len-3] = [byte](($bitLen -shr 16) -band 0xFF)
        $bytes[$len-4] = [byte](($bitLen -shr 24) -band 0xFF)

        # Divide the message into 512 bit chunks
        for($chunk = 0; $chunk -lt $bytes.Length; $chunk += 64)
        {
            $w = ([uint64[]]0 * 80)

            # Copy the chunk into our working array as uints
            for($i = 0; $i -lt 16; $i++){
                $w[$i] = GetBigEndianUInt -bytes $bytes -index ($i*4 + $chunk)
            }

            for($i = 16; $i -lt 80; $i++){
                $w[$i] = LeftRotate -val (TUI ($w[$i-3] -bxor $w[$i-8] -bxor $w[$i-14] -bxor $w[$i-16])) -amount 1
            }

            $a = TUI $h0
            $b = TUI $h1
            $c = TUI $h2
            $d = TUI $h3
            $e = TUI $h4

            # A bunch of crazy stuff
            for($i = 0; $i -lt 80; $i++){
                $k=0
                if($i -lt 20){
                    $f = TUI (($b -band $c) -bor ((-bnot $b) -band $d))
                    $k = TUI 0x5A827999
                }
                elseif($i -lt 40){
                    $f = TUI ($b -bxor $c -bxor $d)
                    $k = TUI 0x6ED9EBA1
                }
                elseif($i -lt 60){
                    $f = TUI (($b -band $c) -bor ($b -band $d) -bor ($c -band $d))
                    $k = TUI 0x8F1BBCDC
                }
                else{
                    $f = TUI ($b -bxor $c -bxor $d)
                    $k = TUI 0xCA62C1D6
                }
            
                $temp = TUI ((LeftRotate -val $a -amount 5) + $f + $e + $k + $w[$i])

                $e = $d
                $d = $c
                $c = LeftRotate -val $b -amount 30
                $b = $a
                $a = $temp
            }

            $h0 = TUI ($h0 + $a)
            $h1 = TUI ($h1 + $b)
            $h2 = TUI ($h2 + $c)
            $h3 = TUI ($h3 + $d)
            $h4 = TUI ($h4 + $e)   
        }

        '{0:X8}{1:X8}{2:X8}{3:X8}{4:X8}' -f $h0, $h1, $h2, $h3, $h4
    }
}
                            
                        
There it is. I may have overused my TUI(To uint) function a little bit, since values larger than 32 bits could actually cause problems. I got most of the implementation details from the wikipedia artical on SHA1.




© 2017 - Peter Sulucz | disclaimer

log in