Skip to content

Conversation

@vcsjones
Copy link
Member

@vcsjones vcsjones commented Aug 28, 2023

Currently, when we want one-shot hashes, we offer, in our public API, HashType.HashData. Often enough we expose other APIs that operate off of HashAlgorithmName which is a strongly-typed string. When we wanted to one-shot with HashAlgorithmName were switching over the name, and calling the appropriate static method.

This however is not trimmer friendly. Those APIs that accept a HashAlgorithmName were pulling in all of the hash types, even if HashAlgorithmName.SHA256 (for example) is the only one used.

Our actual one-shot implementations want string of the hash algorithm name. So we were doing something like this:

graph LR HAN[HashAlgorithmName] subgraph Switch HAN --> MD5 HAN --> SHA1 HAN --> SHA256 HAN --> SHA384 HAN --> SHA512 HAN --> SHA3_256 HAN --> SHA3_384 HAN --> SHA3_512 end MD5 --> HashProviderDispenser SHA1 --> HashProviderDispenser SHA256 --> HashProviderDispenser SHA384 --> HashProviderDispenser SHA512 --> HashProviderDispenser SHA3_256 --> HashProviderDispenser SHA3_384 --> HashProviderDispenser SHA3_512 --> HashProviderDispenser 
Loading

Now we are doing

graph LR HashAlgorithmName --> HashProviderDispenser 
Loading

We still need to do some switching to determine hash algorithm sizes, however we are not rooting any types. The only thing we are using are public constants off of the types, which the compiler will inline.

This also, as a small matter of performance, reduces some indirection as well.

Fixes #91181.

@ghost
Copy link

ghost commented Aug 28, 2023

Tagging subscribers to this area: @dotnet/area-system-security, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

Issue Details

Currently, when we want one-shot hashes, we offer, in our public API, HashType.HashData. Often enough we expose other APIs that operate off of HashAlgorithmName which is a strongly-typed string. When we wanted to one-shot with HashAlgorithmName were switching over the name, and calling the appropriate static method.

This however is not trimmer friendly. Those APIs that accept a HashAlgorithmName were pulling in all of the hash types, even if HashAlgorithmName.SHA256 (for example) is used.

Our actual one-shot implementations want string of the hash algorithm name. So we were doing something like this:

graph LR HAN[HashAlgorithmName] subgraph Switch HAN --> MD5 HAN --> SHA1 HAN --> SHA256 HAN --> SHA384 HAN --> SHA512 HAN --> SHA3_256 HAN --> SHA3_384 HAN --> SHA3_512 end MD5 --> HashProviderDispenser SHA1 --> HashProviderDispenser SHA256 --> HashProviderDispenser SHA384 --> HashProviderDispenser SHA512 --> HashProviderDispenser SHA3_256 --> HashProviderDispenser SHA3_384 --> HashProviderDispenser SHA3_512 --> HashProviderDispenser 
Loading

Now we are doing

graph LR HashAlgorithmName --> HashProviderDispenser 
Loading

We still need to do some switching to determine hash algorithm sizes, however we are not rooting any types. The only thing we are using are public constants off of the types, which the compiler will inline.

This also, as a small matter of performance, reduces some indirection as well.

Fixes #91181.

Author: vcsjones
Assignees: -
Labels:

area-System.Security

Milestone: -
@vcsjones vcsjones requested a review from bartonjs August 28, 2023 00:32
Copy link
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

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

LGTM, thank you for providing the explanation and the mermaid graph, so I could learn something by reviewing this PR. 👍

@vcsjones vcsjones merged commit 919be00 into dotnet:main Aug 28, 2023
@vcsjones vcsjones deleted the hash-aot-rooting branch August 28, 2023 10:45
@vcsjones vcsjones added this to the 9.0.0 milestone Aug 28, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Sep 28, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

2 participants