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

Need ProtectedData support on non-Windows #22886

Closed
SteveL-MSFT opened this issue Jul 21, 2017 · 9 comments
Closed

Need ProtectedData support on non-Windows #22886

SteveL-MSFT opened this issue Jul 21, 2017 · 9 comments
Milestone

Comments

@SteveL-MSFT
Copy link
Contributor

Current package https://dotnet.myget.org/F/dotnet-core/api/v2/package/System.Security.Cryptography.ProtectedData/4.0.0-rc3-24022-00 throws PlatformNotSupported on non-Windows.

This feature is needed by PowerShell and Nuget and it doesn't make sense for everyone to roll their own.

The original issue has been Closed so creating this new one to track.

@bartonjs
Copy link
Member

We have no plans to do this. It requires OS features that are only available on Windows.

@reddwarf666
Copy link

Trying to read and keep track of this issue is very difficult on github, cross references all over the place and all seem to get closed without any actual resolvement.

Will we be able to use this feature on MacOS / Linux or won't we?

@bartonjs
Copy link
Member

@reddwarf666 No, this API will only ever work on Windows. (and if we were to ever make something that worked cross-platform (which I don't forsee) it would probably be a new API, not this one).

ProtectedData is part of Windows DPAPI (Data Protection API). It encrypts the data using an algorithm of its choice and a key that it probably makes up on the spot. That key it needs to write down, but the whole point of the API is to not require a key, so it encrypts the key with another key.

How does it get the other key? For user-scoped data it uses a key that it derives off of your account. The simplest form is to say that it derives something other than your logon key from your password, such as by using PBKDF2 with a special DPAPI-engineered salt (since I assume it also works on systems where the user has only ever logged in with a smartcard, it must use something other than the password per se),

So, on Windows we call an API that we give some data to, and it knows who the user is, and it encrypts the data. Huzzah. It also has a machine scope, so any user on this computer can read it, but no other computer can recover it. Huzzah.

On macOS the closest equivalent is a keychain. But with the keychain things are different... for one, you can browse it with the Keychain Access program. So if we generate a random KEK and we shove it in the keychain and you delete it then the data is unrecoverable. What keychain do we use? If we make a custom one, what would we do on macOS? How would we do machine-scoped protection in a manner that worked for non-administrators?

On Linux there's not even something like Keychain. If this was 1981 we could read the user entry out of passwd and use their password hash as the input to a KDF for building the KEK. But now security exists, and that's hidden in the (/etc/)shadow. The only way to capture user secrets is at login with a PAM module. So now .NET needs to write an authentication model purely for the purposes of sniffing your password. And SSH needs to do something... So maybe we use a PAM module to sneak a peek at the shadow file. Vunderbar. Oh, except accounts can exist that allow SSH login which don't have passwords. Oh, and we still didn't solve the machine-scoped thing.

In the end, DPAPI is a Windows feature. The ProtectedData class is a very thin wrapper over DPAPI's CryptProtectData (and CryptUnprotectData). There's no parallel on Linux or macOS (that I can find). Without a thing specifically being a DPAPI port to another platform we couldn't really use it, because it might have different constraints (doesn't work after a reboot; doesn't work after a hostname change; doesn't work if the first device returned in NIC enumeration changes (or changes MAC address); et cetera) that we just wouldn't know about, and couldn't control, and then the API becomes dangerous to rely on.

What we have in .NET Core is clear. On Windows it does whatever DPAPI does. On non-Windows it does what Windows DPAPI does on those platforms: not exist.

@reddwarf666
Copy link

@bartonjs Thanks for the extensive write-up, appreciated. I guess we have to live with this reality that not everything will be cross platform. I do hope a general solution will be found but I understand the issue a bit better now.

@atifaziz
Copy link

karelz modified the milestone: 2.1.0 on 14 Aug

@karelz This issue was closed but then got assigned to the 2.1.0 milestone. Does that mean it is being addressed somehow now despite the technical challenges enumerated by @bartonjs?

@karelz
Copy link
Member

karelz commented Sep 25, 2017

No, milestone just captures when it was closed, it does not imply resolution as Fixed.

marek-safar referenced this issue in mono/mono Jul 9, 2018
As part of #7589 

- CoreFX import only for Windows platform (no support for non-Windows platforms, see https://github.com/dotnet/corefx/issues/22510)
- left Mono managed implementation for non-Windows platforms
- removed DataProtectionScope parameter value check (no such a check in CoreFX and NET Framework, see dotnet/corefx#30726) and couple of related unit tests
- added CoreFX xunit tests
@tmds
Copy link
Member

tmds commented Jan 8, 2019

@bartonjs NuGet uses ProtectedData for encrypting passwords (NuGet/Home#1851). Because it is not available, the only option on non-Windows is plain text passwords.

mono has an implementation of ProtectedData. When the API is first used, a keypair is generated and stored in the file system with appropriate permissions. Then that key is used for encrypting/decrypting. Perhaps corefx can implement something similar.

Lack of this API means storing passwords plain text or people rolling their own. Providing an implementation similar to mono seems better than those options.

@tmds
Copy link
Member

tmds commented Jan 15, 2019

@bartonjs could this be implemented in a similar way as Mono? See comment above.

@bartonjs
Copy link
Member

@tmds I think I already covered that in https://github.com/dotnet/corefx/issues/22510#issuecomment-317197092.

NuGet is free to base something off of the Mono implementation of ProtectData (with all the bugs and policy violations fixed), but the real DPAPI is complicated and provides much better guarantees (assuming that https://www.passcape.com/index.php?section=docsys&cmd=details&id=28 is accurate); and I'm not comfortable with "On Windows, a user-scoped secret can't be forced by an admin" (at least, if you never log in again) and "On Linux, well... sorry."

Could a DPAPI-inspired solution be created? Sure, but it would almost certainly be a new, different API.

@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 2.1.0 milestone Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants