Skip to content

Add Get-StringHash and Get-FileHash cmdlets - #3024

Merged
Jason Shirk (lzybkr) merged 7 commits into
PowerShell:masterfrom
iSazonov:gethash
Feb 4, 2017
Merged

Jason Shirk (lzybkr) merged 7 commits into
PowerShell:masterfrom
iSazonov:gethash

Conversation

@iSazonov

Copy link
Copy Markdown
Collaborator

Close #2731

  1. Rewrite Get-FileHash on C# and refactoring tests
    The original Get-FileHash output type is Microsoft.Powershell.Utility.FileHash. The type was defined by ExtendedTypeDefinition. It is not C# type and reported as PSCustomObject.
    Therefore, the output type was changed and now it is native C# type Microsoft.PowerShell.Commands.FileHashInfo.

  2. Add new cmdlet Get-StringHash and add tests
    The original idea was to add a InputString parameter to the common cmdlet but due to a conflict with the Path parameter (paths is strings too!) I had to make a new cmdlet to provide a pipeline support for the InputString parameter.

@lzybkr Jason Shirk (lzybkr) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PowerShell/powershell-committee - needs to review the new cmdlet - parameters, output type, allowing null.

$hashSHA256forEmptyString = "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855"

# Keep "sHA1" below! It is for testing that the cmdlet accept a hash algorithm name in any case!
$testcases =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the use of a common variable name, this should be moved closer to the use to limit the scope.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.


Context "Default result tests" {
It "Should default to correct hash (SHA256)" {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider removing some of the blank lines just after or just before opening/closing braces.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

$result[1] | Should Be $hashSHA256forEmptyString
}

It "Should be able to set the default hash algorithm" {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is unnecessary - there is no reason to test PSDefaultParameterValues on specific cmdlets, the generic tests for PSDefaultParameterValues are sufficient.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is from original tests.
Removed.


It "Should not throw for empty or null input string" {
Get-StringHash -InputString "" | Should Be $hashSHA256forEmptyString
Get-StringHash -InputString $null | Should Be $null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really desirable? Allowing $null?

@iSazonov Ilya (iSazonov) Jan 24, 2017 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about this example:

$stringarray | Get-StringHash 

If the string array contains a null string member then we throw - is this the desired behavior?
The following example does not cause a exception:

"a",$null | Select-String -Pattern ".*"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$null is not passed through the pipeline and Select-String allows $null anyway, so that's not a good example.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but key is that null string don't throw an exception here.

@@ -0,0 +1,62 @@
Describe "Get-StringHash" -Tags "CI" {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expect very few changes to this feature once merged, so maybe we don't need the tests in CI.

@iSazonov Ilya (iSazonov) Jan 24, 2017 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can change it after the merger. (Or just before.)

/// <summary>
/// Create FileHashInfo object and output it
/// </summary>
private void WriteHashResult(String Algorithm, String hash, String path)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use lowercase string.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

/// </summary>
/// <value></value>
[Parameter(Position = 1)]
[ValidateSet(HashAlgorithmNames.SHA1,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PowerShell version supports additional algorithms - why are they not included here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is from original cmdlet and HashAlgorithmNames class.
If there are other useful algorithms, please give a link.
And whether we should do something specifically for Mac?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the ValidateSet use here, the original function has:

  • MACTripleDES
  • MD5
  • RIPEMD160
  • SHA1
  • SHA256
  • SHA384
  • SHA512

I suppose it's not surprising that a couple of these are missing for .Net Core.

We should probably add the missing algorithms for Windows PowerShell or explore alternative implementations to that we can have completely portable scripts.

/cc Steve Lee (@SteveL-MSFT)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jason Shirk (@lzybkr) if .Net Core doesn't support those, we should treat it as a separate issue (not block this PR). however, we should see if .Net Core will implement them or why they no longer support it (patents? no longer secure?)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe these are hashing algorithms, so security isn't the issue. My guess is less demand.

But the real question here - are we OK with a PR that would be a breaking change to Windows PowerShell if we took this code back to Windows as is?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The security concern is that hashes are used to determine if something (like a file/package) has been modified. However, SHA1, for example, has been proven that you can generate collisions meaning that it is feasible someone could modify a file and produce the same resulting SHA1 hash so it appears to be legit.

We can discuss this at the Committee meeting.

It "Should default to correct hash algorithm" {
$result = Get-FileHash $testDocument
BeforeAll {
New-Variable testDocument -Value (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath assets) -ChildPath testablescript.ps1) -Scope Global -Force

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A test shouldn't normally create a variable in global scope.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

}

$result.Algorithm | Should Be "MD5"
It "Should be able to set the default hash algorithm" {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test should not be necessary, PSDefaultParameterValues is already well tested.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

$result.Algorithm | Should Be "SHA256"
}
# Keep "sHA1" below! It is for testing that the cmdlet accept a hash algorithm name in any case!
$testcases =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be moved closer to the use to limit the scope of the variable.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@lzybkr Jason Shirk (lzybkr) added the Review - Committee The PR/Issue needs a review from the PowerShell Committee label Jan 23, 2017
@{ algorithm = "SHA384"; hash = "656215B6A07011E625206F43E57873F49AD7B36DFCABB70F6CDCE2303D7A603E55D052774D26F339A6D80A264340CB8C" },
@{ algorithm = "SHA512"; hash = "C688C33027D89ACAC920545471C8053D8F64A54E21D0415F1E03766DDCDA215420E74FAFD1DC399864C6B6B5723A3358BD337339906797A39090B02229BF31FE" },
@{ algorithm = "MD5"; hash = "7B09811D1631C9FD46B39D1D35522F0A" }
New-Variable testDocument -Value (Join-Path -Path (Join-Path -Path $PSScriptRoot -ChildPath assets) -ChildPath testablescript.ps1) -Force

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't this just use $testDocument = Join-Path ...?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@iSazonov

Copy link
Copy Markdown
Collaborator Author

@PowerShell/powershell-committeeTeam
Should we introduce a new type 'Microsoft.PowerShell.Commands.StringHashInfo' for Get-StringHash output similar to Get-FileHash output?

+ $testDocument' in test
@SteveL-MSFT Steve Lee (SteveL-MSFT) added the Breaking-Change breaking change that may affect users label Jan 26, 2017
@lzybkr

Copy link
Copy Markdown
Contributor

@PowerShell/powershell-committee has decided we need an RFC for the Get-StringHash cmdlet.

The biggest concern was how PowerShell will convert anything to string, so the cmdlet will happily hash objects in a potentially unexpected way.

The output type was also of some concern when combined with allowing null because it will be difficult to match input with output. We think the output needs the original object in addition to the hash.

@lzybkr Jason Shirk (lzybkr) added Committee-Reviewed PS-Committee has reviewed this and made a decision and removed Review - Committee The PR/Issue needs a review from the PowerShell Committee labels Jan 26, 2017
@lzybkr

Copy link
Copy Markdown
Contributor

The committee also agreed that we do not need any updates with regards to the algorithms supported - we've marked the PR wit Breaking Change so we can document the difference between Windows PowerShell and PowerShell Core.

@iSazonov

Copy link
Copy Markdown
Collaborator Author

What will be the road map for the PR?
Could I remove Get-StringHash code from the PR?

I do not have the forces for the RFC to write the big text correctly in English.
Can we ask the author Keith Hill (@rkeithhill) of the Get-StringHash idea to start this RFC?

@lzybkr

Copy link
Copy Markdown
Contributor

By all means - remove Get-StringHash from the PR.

Your English seems more than sufficient to write a RFC, but if Keith Hill (@rkeithhill) is up for it, I assume he'll jump in.

Removed for future RFC.
@iSazonov

Copy link
Copy Markdown
Collaborator Author

Jason Shirk (@lzybkr) I create new PR with RFC PowerShell/PowerShell-RFC#63

Now Get-StringHash was removed from the PR.
Travis again temporary failed 😕

@iSazonov

Copy link
Copy Markdown
Collaborator Author

Jason Shirk (@lzybkr) Should I do something else in the PR?

@lzybkr Jason Shirk (lzybkr) self-assigned this Feb 4, 2017
@lzybkr
Jason Shirk (lzybkr) merged commit 2981806 into PowerShell:master Feb 4, 2017
@iSazonov

Copy link
Copy Markdown
Collaborator Author

Jason Shirk (@lzybkr) Thanks!

@iSazonov
Ilya (iSazonov) deleted the gethash branch April 17, 2020 12:19
Thatgfsj (Thatgfsj) pushed a commit to Thatgfsj-contribs/PowerShell that referenced this pull request Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Breaking-Change breaking change that may affect users Committee-Reviewed PS-Committee has reviewed this and made a decision

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants