8000 [Security] Saltless Encoder Interface by zanbaldwin · Pull Request #21620 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Security] Saltless Encoder Interface #21620

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

Merged
merged 1 commit into from
Sep 27, 2017
Merged

[Security] Saltless Encoder Interface #21620

merged 1 commit into from
Sep 27, 2017

Conversation

zanbaldwin
Copy link
Member
@zanbaldwin zanbaldwin commented Feb 15, 2017
Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets
License MIT
Doc PR

A new interface for encoders that do not require a user-generated salt (generate their own built-in) as suggested by @stof (comment), this will become useful as more password encoders are added in the future (such as #21604).

8000
@zanbaldwin zanbaldwin changed the title Saltless Encoder Interface [Security] Saltless Encoder Interface Feb 15, 2017
namespace Symfony\Component\Security\Core\Encoder;

/**
* SaltlessEncoderInterface is the interface for encoders that do not require a
Copy link
Member

Choose a reason for hiding this comment

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

I would say ```is a marker interface for encoders...``

@@ -93,9 +93,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
$emptySalt = $input->getOption('empty-salt');

$encoder = $this->getContainer()->get('security.encoder_factory')->getEncoder($userClass);
$bcryptWithoutEmptySalt = !$emptySalt && $encoder instanceof BCryptPasswordEncoder;
$saltless = !$emptySalt && $encoder instanceof SaltlessEncoderInterface;
Copy link
Member

Choose a reason for hiding this comment

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

should be $saltlessWithoutEmptySalt to describe what it really detects

@zanbaldwin
Copy link
Member Author

Awesome, thanks for the feedback so quickly, @stof! I wasn't exactly sure how to implement it but wanted to shove it on GitHub before I forgot about it 😄

@stof
Copy link
Member
stof commented Feb 15, 2017

I'm not just not sure about the naming of the interface. These encoders are still using a salt, but they generate it internally and don't require storing it separately for the verification step.

@symfony/deciders do you have a better idea for the naming ?

@javiereguiluz
Copy link
Member

I like this idea a lot ... but I don't like the proposed name SaltlessEncoderInterface. Here are some alternatives:

  1. If "salt-less hashers" are the future, why not call this simply: EncoderInterface
  2. In the Wikipedia, these hashers are classified under "Key derivation functions". It's an ugly name, but this could be called KeyDerivationEncoderInterface
  3. Another classification of these hashers is via its syntax/format. They use the "Modular Crypt Format". So, why not ModularEncoderInterface
  4. Finally, if we want to fix an historical issue with the "encoder" name ... why not call this what it really is: HasherInterface

@zanbaldwin
Copy link
Member Author

I really like the idea of moving away from the Encoder name since password hashes cannot be decoded.

@stof
Copy link
Member
stof commented Feb 15, 2017

@javiereguiluz this interface is just a marker one. so I would not give it a name which is more generic than the real implementation.

If I was designing this system from scratch, I would change 2 things:

  • talk about hashing, not encoding
  • remove the salt from all signatures, by forcing all encoders to generate it internally and to embed it in the hash for verification (i.e. what our bcrypt and argon2i encoders are doing).

However, we cannot easily switch to such system, as it implies a BC break in the storage format for people not using bcrypt today, and so writing a migration layer would be very hard.
I already though about doing such change for Symfony 4, and I gave up for now.

But starting to talk about hashing now in a marker interface for the existing API would be a mistake IMO (more confusing than anything else)

@linaori
Copy link
Contributor
linaori commented Feb 16, 2017

I think for now "Encoder" is good enough. However, I would like to move on to a name change (soon tm) to "Hasher" because it's already confusing and complex without this naming issue.

@zanbaldwin
Copy link
Member Author
8000

I've renamed SaltlessEncoderInterface to EncoderInterface, should the following (variable name and note message) be updated for clarification too?

} elseif ($saltlessWithoutEmptySalt) {
    $io->note('Saltless encoder used: the encoder generated its own built-in salt.');

@nicolas-grekas nicolas-grekas added this to the 3.3 milestone Feb 18, 2017
@stof
Copy link
Member
stof commented Mar 20, 2017

@zanderbaldwin EncoderInterface is a bad name. As this is only a marker interface, not a feature interface, the name must describe what it is marking. EncoderInterface is far too generic

@zanbaldwin
Copy link
Member Author

Sure. From the comments above I'm not sure what to name the interface - was anything concretely decided on?

@sstok
Copy link
Contributor
sstok commented Apr 12, 2017

In the Wikipedia, these hashers are classified under "Key derivation functions". It's an ugly name, but this could be called KeyDerivationEncoderInterface.

https://en.wikipedia.org/wiki/Key_derivation_function

A Key derivation function is something completely else, a Key derivation is used a generate a "passphrase", to be used an encryption key. As using your password directly is considered highly insecure because of the minimum required length of key, which is not achieved with a 10 character password (you need at least 128bits).

PBKDF (Password-Based Key Derivation Function) is actually designed for this and for NOT for passwords, because it's slow and not fully protected against memory attacks. (I was not aware of that at the time 😅 ).

@zanbaldwin
Copy link
Member Author

I think that whatever is decided it's going to be a compromise - so I'll leave it up to the members of @symfony/deciders to inform me what the interface should be called 🙂

@nicolas-grekas nicolas-grekas modified the milestones: 3.3, 3.4 Apr 26, 2017
@nicolas-grekas
Copy link
Member

@stof any help to move this one forward?

@weaverryan
Copy link
Member

SelfSaltingEncoderInterface. The idea of "salt" exists in core already, and this very simply is an encoder that does not require a salt to be passed in explicitly.. it handles it on its own.

@javiereguiluz
Copy link
Member

I like Ryan's proposal.

@zanbaldwin
Copy link
Member Author

I've implemented Ryan's proposal 👍

@stof
Copy link
Member
stof commented Sep 26, 2017

I like it as well

} elseif ($bcryptWithoutEmptySalt) {
$errorIo->note('Bcrypt encoder used: the encoder generated its own built-in salt.');
} elseif ($saltlessWithoutEmptySalt) {
$errorIo->note('Saltless encoder used: the encoder generated its own built-in salt.');
Copy link
Member

Choose a reason for hiding this comment

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

should be changed from Saltless to Self-salting based on the renaming

@nicolas-grekas
Copy link
Member

I think the failure is a false positive related to this security-bundle requiring symfony/security, but the CI building syfmony/security-http. That's a bug in the CI script. But not for this PR.

@zanbaldwin
Copy link
Member Author

Does the target branch need to be changed from master to 3.4?

@nicolas-grekas
Copy link
Member

Yes please

@zanbaldwin zanbaldwin changed the base branch from master to 3.4 September 26, 2017 15:26
@nicolas-grekas
Copy link
Member

tests are legitimately failing, both on Windows and Linux

@@ -115,11 +115,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
$userClass = $this->getUserClass($input, $io);
$emptySalt = $input->getOption('empty-salt');

$encoderFactory = $this->encoderFactory ?: $this->getContainer()->get('security.encoder_factory');
Copy link
Member

Choose a reason for hiding this comment

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

This is a BC layer, it must be kept

Copy link
Member
@chalasr chalasr Sep 27, 2017

Choose a reason for hiding this comment

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

Can you revert? This is what breaks tests

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry about that. Changed it back.

A new interface for all encoders that do not require a user-generated salt.
@zanbaldwin
Copy link
Member Author
zanbaldwin commented Sep 27, 2017

Can anyone clarify if the test is now failing for PHP: 7.1 deps=high because the Security component is installed via Composer for the SecurityBundle tests, so therefore the changes in this PR for the Security component are not used when the tests are run?

Because I get the following:

$ cd "<repoRoot>"
# On pull request branch ("zanbaldwin:saltless-encoder-interface").
$ composer install
# Package "symfony/phpunit-bridge" installed.
$ cd "<repoRoot>/src/Symfony/Bundle/SecurityBundle"

$ composer install
# Package "symfony/security" installed at version "3.4.x-dev 2910bac".
$ ../../../../vendor/bin/simple-phpunit
# Tests fail :(

$ rm -rf vendor/symfony/security
$ ln -s ../../../../Component/Security vendor/symfony/security
$ ../../../../vendor/bin/simple-phpunit
# Tests pass! :)

@ogizanagi
Copy link
Contributor

@zanbaldwin : Yes this is expected. Tests will pass once the PR code is merged up to master.

AppVeyor failure is not related.

@stof stof dismissed chalasr’s stale review September 27, 2017 13:28

Bad change has been reverted, as requested

@stof
Copy link
Member
stof commented Sep 27, 2017

Thank you @zanbaldwin.

@stof stof merged commit 7c4aa0b into symfony:3.4 Sep 27, 2017
stof added a commit that referenced this pull request Sep 27, 2017
This PR was merged into the 3.4 branch.

Discussion
----------

[Security] Saltless Encoder Interface

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        |

A new interface for encoders that do not require a user-generated salt (generate their own built-in) as suggested by @stof ([comment](https://github.com/symfony/symfony/pull/21604/files#r101225470)), this will become useful as more password encoders are added in the future (such as #21604).

Commits
-------

7c4aa0b Saltless Encoder Interface
@zanbaldwin zanbaldwin deleted the saltless-encoder-interface branch September 27, 2017 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants
0