Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Developers targeting browser-wasm can use Web Crypto APIs #40074

Closed
15 of 24 tasks
Tracked by #43767 ...
marek-safar opened this issue Jul 29, 2020 · 62 comments
Closed
15 of 24 tasks
Tracked by #43767 ...

Developers targeting browser-wasm can use Web Crypto APIs #40074

marek-safar opened this issue Jul 29, 2020 · 62 comments
Assignees
Labels
arch-wasm WebAssembly architecture area-System.Security Cost:L Work that requires one engineer up to 4 weeks Priority:1 Work that is critical for the release, but we could probably ship without Team:Libraries User Story A single user-facing feature. Can be grouped under an epic.
Projects
Milestone

Comments

@marek-safar
Copy link
Contributor

marek-safar commented Jul 29, 2020

We want to avoid shipping OpenSSL for Browser as that’s not something that aligns well with web nature of WebAssembly as well as it has noticeable impacts on the size of the final app. This would also save us from having to deal with zero-day vulnerabilities as well as support for crypto algorithms which are only secure if they use special CPU instructions (RNG and AES for example).

Using the platform native crypto functions is the preferred solution as it does not have any noticeable size and it’s also the most performant solution. All browser have nowadays support for Crypto APIs which we should be able to use to implement the core crypto functions required by BCL.

Relevant documentation can be found at https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto. The tricky part will be to deal with the async nature of these APIs but we could introduce new async APIs to make the integration easier.

.NET has support for old/obscure algorithms and also other features like certificates which are not relevant in browser space and for them, we would keep throwing PNSE.

Design Proposal

The design proposal for how we will enable cryptographic algorithms in .NET for WebAssembly can be found here:
https://github.com/dotnet/designs/blob/main/accepted/2021/blazor-wasm-crypto.md

We intend on providing the most secure implementations of cryptographic algorithms when available. On browsers which support SharedArrayBuffer, we will utilize that as a synchronization mechanism to perform a sync-over-async operation, letting the browser's secure SubtleCrypto implementation act as our cryptographic primitive. On browsers which do not support SharedArrayBuffer, we will fall back to in-box managed algorithm implementations of these primitives.

Where managed algorithm implementations are needed, they can be migrated from the .NET Framework Reference Source.

Work Items

  • SHA1
  • SHA256
  • SHA384
  • SHA512
  • HMACSHA1
  • HMACSHA256
  • HMACSHA384
  • HMACSHA512
  • AES-CBC
    • AES-ECB and AES-CFB should throw PlatformNotSupportedException, as they are not available in webcrypto
  • PBKDF2 (via Rfc2898DeriveBytes)
  • HKDF

Acceptance Criteria

  • Integrate into arch-wasm infrastructure
  • Ensure a productive development/testing workflow with WebAssembly
  • Get all existing unit tests for the algorithms passing in WebAssembly
  • Look for opportunities to improve argument validation
  • Look for opportunities to modernize the code, such as using Span
  • Validate end-to-end scenarios in desktop browsers that support SharedArrayBuffer
  • Validate end-to-end scenarios in mobile browsers that support SharedArrayBuffer
  • Validate end-to-end scenarios in desktop browsers that do not support SharedArrayBuffer
  • Validate end-to-end scenarios in mobile browsers that do not support SharedArrayBuffer

Issues to address

@marek-safar marek-safar added arch-wasm WebAssembly architecture area-System.Security labels Jul 29, 2020
@marek-safar marek-safar added this to the 6.0.0 milestone Jul 29, 2020
@ghost
Copy link

ghost commented Jul 29, 2020

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

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Jul 29, 2020
@marek-safar marek-safar removed the untriaged New issue has not been triaged by the area owner label Jul 29, 2020
@jaykrell
Copy link
Contributor

jaykrell commented Aug 6, 2020

only secure if they use special CPU instructions (RNG and AES for example

Really "only secure"? Or just faster?

@bartonjs
Copy link
Member

bartonjs commented Aug 7, 2020

Really "only secure"? Or just faster?

AES is literally only secure with dedicated hardware instructions on modern CPUs. All software implementations are subject to various timing problems that ultimately leak the key to a dedicated attack (http://cr.yp.to/antiforgery/cachetiming-20050414.pdf).

@GrabYourPitchforks
Copy link
Member

As part of this work item, we should also verify that RandomNumberGenerator is correctly plumbed down to crypto.getRandomValues. Right now it's plumbed through /dev/random, which I think the Mono wasm engine ties through correctly, but it's always good to remove indirection and points of failure where possible.

@kjpou1
Copy link
Contributor

kjpou1 commented Oct 14, 2020

Looking into support and providing a prototype that works with browser os.

@marek-safar marek-safar added the User Story A single user-facing feature. Can be grouped under an epic. label Nov 5, 2020
@marek-safar marek-safar changed the title Using Web Crypto APIs for browser-wasm cryptography implementation Web Crypto APIs are available to users targeting browser-wasm Nov 5, 2020
@marek-safar marek-safar added Cost:L Work that requires one engineer up to 4 weeks Priority:1 Work that is critical for the release, but we could probably ship without and removed area-System.Security labels Nov 5, 2020
eerhardt added a commit to eerhardt/runtime that referenced this issue Jun 17, 2022
Implement the browser "native" portion for HMAC on Browser WASM.

I also made a few refactoring / simplifications where necessary.

Contributes to dotnet#40074
eerhardt added a commit that referenced this issue Jun 21, 2022
* Use crypto.subtle for HMAC on Browser WASM

Implement the browser "native" portion for HMAC on Browser WASM.

I also made a few refactoring / simplifications where necessary.

Contributes to #40074
eerhardt added a commit to eerhardt/runtime that referenced this issue Jun 30, 2022
Implement the browser "native" portion for AES on Browser WASM.

There are two issues to solve .NET's Aes API on crypto.subtle:
1. The .NET API supports streaming while crypto.subtle only supports "one shot" APIs.
2. The .NET API supports multiple padding modes while crypto.subtle only supports PKCS7.

To solve these issues, we use the following approach:

1. We only invoke crypto.subtle with complete AES "blocks" of data. This allows us to make assumptions about the padding behavior.
2. To implement streaming, remember the last block of the previous cipher text to use as the IV for the next stream of data.
3. When encrypting, since we have a complete block of data and crypto.subtle uses PKCS7 padding, strip off the last block of cipher text which will always be a full block of padding.
4. When decrypting do the inverse of encrypting - append an encrypted block of padding to the cipher text so crypto.subtle will return the full message as plain text.

Other changes:
- Make a few refactoring / simplifications where necessary.
- SubtleCrypto doesn't support 192 bit AES keys, so no longer support AES-192 on Browser.

Contributes to dotnet#40074
eerhardt added a commit that referenced this issue Jul 6, 2022
* Use crypto.subtle for AES on Browser WASM

Implement the browser "native" portion for AES on Browser WASM.

There are two issues to solve .NET's Aes API on crypto.subtle:
1. The .NET API supports streaming while crypto.subtle only supports "one shot" APIs.
2. The .NET API supports multiple padding modes while crypto.subtle only supports PKCS7.

To solve these issues, we use the following approach:

1. We only invoke crypto.subtle with complete AES "blocks" of data. This allows us to make assumptions about the padding behavior.
2. To implement streaming, remember the last block of the previous cipher text to use as the IV for the next stream of data.
3. When encrypting, since we have a complete block of data and crypto.subtle uses PKCS7 padding, strip off the last block of cipher text which will always be a full block of padding.
4. When decrypting do the inverse of encrypting - append an encrypted block of padding to the cipher text so crypto.subtle will return the full message as plain text.

Other changes:
- Make a few refactoring / simplifications where necessary.
- SubtleCrypto doesn't support 192 bit AES keys, so no longer support AES-192 on Browser.

Contributes to #40074

* Use an empty array to create encrypted padding block.
eerhardt added a commit to eerhardt/runtime that referenced this issue Jul 7, 2022
Marks the APIs as supported on Browser, and enables Rfc2898 tests on Browser WASM.
Use SubtleCrypto deriveBits API to implement one shot Pbkdf2.

Contributes to dotnet#40074
eerhardt added a commit that referenced this issue Jul 9, 2022
* Enable Rfc2898DeriveBytes on Browser WASM

Marks the APIs as supported on Browser, and enables Rfc2898 tests on Browser WASM.
Use SubtleCrypto deriveBits API to implement one shot Pbkdf2.

* Mark HKDF as supported on Browser and enable tests

Contributes to #40074
@radical radical modified the milestones: 7.0.0, 8.0.0 Aug 12, 2022
@jeffhandley jeffhandley modified the milestones: 8.0.0, 7.0.0 Aug 13, 2022
@jeffhandley
Copy link
Member

We've concluded that using the SharedArrayBuffer approach via a worker is not yielding the end-to-end experience or quality necessary to release this integration. As a result, we've changed the scope of what will be included in .NET 7 to no longer include AES-CBC. Additionally, instead of using SubtleCrypto via the SharedArrayBuffer to reach the native implementations of other algorithms, we will rely wholly on managed implementations.

Please see #73858 for more information and refer to the design document for more information about the managed implementation expectations.

Where native implementations need to be accessed, they will need to be called via JavaScript interop.

.NET 6.0 automation moved this from Cut to Completed Aug 13, 2022
@teo-tsirpanis teo-tsirpanis closed this as not planned Won't fix, can't repro, duplicate, stale Aug 13, 2022
@teo-tsirpanis teo-tsirpanis moved this from Completed to Cut in .NET 6.0 Aug 13, 2022
@teo-tsirpanis teo-tsirpanis moved this from Cut to Completed in .NET 6.0 Aug 13, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Sep 14, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
arch-wasm WebAssembly architecture area-System.Security Cost:L Work that requires one engineer up to 4 weeks Priority:1 Work that is critical for the release, but we could probably ship without Team:Libraries User Story A single user-facing feature. Can be grouped under an epic.
Projects
.NET 6.0
  
Completed
Development

No branches or pull requests