Skip to content

Conversation

@defuse
Copy link
Owner

@defuse defuse commented Oct 16, 2015

See the commit messages.

Refactoring
===================

Removes unnecessary inheritance. Using inheritance adds an extra mental burden
of remembering where methods and variables are defined. With static inheritance,
'self::' can either mean "the file you're looking at" or "some other file."

Moves the encoding functions into Encoding.php.

I'm guessing the purpose of the inheritance was to be able to use 'protected' to
prevent the user of the library from calling internal functions. This patch uses
a different technique: There are only public and private methods, and the user
is allowed to any public method of "user-usable" classes. So: We tell the user
about Crypto and the new Encoding, but we don't tell them Core exists. The user
should never be calling functions on Core, but our classes (and test cases) are
allowed to. PHP doesn't let you make classes private to a namespace, so there's
currently nothing *stopping* the user from doing that, but I think it's a better
trade-off than the extra mental burden of using static inheritance.

De-duplicates the magic number by defining Core::HEADER_MAGIC and
Core::HEADER_MAGIC_FILE constants.

The normal encryption and file encryption's config getters are now completely
independent. This reduces coupling and increases cohesion, at the cost of
duplication of the settings (but, conceptually, we may want to vary the file and
normal encryption settings independently.)

Increases security to downgrade attacks. The old code would simply fail if the
version header was legacy. The new code allows you to pass a $min_ver_header to
getVersionConfigFromHeader(), which means "I'm giving you a header, and I want
you to give me the settings for that header, but I also want you to check that
the version in that header is bigger than $min_ver_header." This is used by
decrypt to ensure that it isn't decrypting a legacy ciphertext (i.e. the user
has to call legacyDecrypt). This will be useful in the future if, say, the 2.0
configuration has a security vulnerability such that changing a 2.1 ciphertext's
header to say 2.0 would make 2.1 ciphertexts vulnerable.

(This downgrade prevention hasn't been implemented for the File class, but it
should be soon.)

Currently, there is no API for checking whether a ciphertext is legacy. That
should be added in the future.

In a couple places in the old code, $config was set to some hard-coded version
if it wasn't passed in to the function. For each of those cases, I removed the
code that did that, and ensured that a valid $config is always passed in.

Protocol changes:
===================

Different HKDF infos are used for the three different things:

    - Legacy encryption and decryption (keeps the old values)
    - 2.0 encryption and decryption (adds "V2")
    - File encryption and decryption (adds "V2File")

This ensures that if the same key is re-used for all three, the same keys aren't
re-used (potentially avoiding subtle interactions that could lead to a break).

I got rid of the timing-safe code in getVersionConfig(). The differences in
configuration returned (CBC vs CTR, etc.) reveal which version it is anyway, so
there's no point trying to timing-safe-ize those functions.
@defuse
Copy link
Owner Author

defuse commented Oct 16, 2015

@paragonie-scott: It would be wonderful if you could review this PR, and, at your leisure, argue against removing the inheritance if you think it's valuable.

@defuse
Copy link
Owner Author

defuse commented Oct 16, 2015

(What it does is written in the commit message)

@defuse defuse mentioned this pull request Oct 17, 2015
@defuse defuse mentioned this pull request Oct 17, 2015
@defuse defuse mentioned this pull request Oct 17, 2015
@paragonie-scott
Copy link
Collaborator

Aside from the failure caused by #22 (and possibly any errors that failure is hiding), this looks very good to me. I like the way you organize everything. 👍

(I am of course going to re-read the whole PR as soon as it's ready to be finalized.)

@paragonie-scott
Copy link
Collaborator

It would be wonderful if you could review this PR, and, at your leisure, argue against removing the inheritance if you think it's valuable.

The only reason I used inheritance in my initial PR #78 was to expose common methods that the derived classes (Crypto and File) could use, but were not public. It's not a feature I feel super strongly about, and someone could always make

class CryptoProxy extends \Defuse\Crypto\Core {
    public function getInaccessibleMethod($method, $args = []) {
        return parent::$method(...$args);
    }
}

and there's nothing inheritance can do to stop this.

src/File.php Outdated
Copy link
Collaborator

Choose a reason for hiding this comment

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

For this, shouldn't we use the header length constant?

@paragonie-scott
Copy link
Collaborator

Aside from a few very minor things this looks good to me. I do have one suggestion but I'll open an issue for that.

@defuse
Copy link
Owner Author

defuse commented Oct 19, 2015

Okay, fixed those minor issues, and the travis testing is passing. I think it's time to land this!

@defuse defuse merged commit 6c1d4bc into v2.0 Oct 19, 2015
@paragonie-scott paragonie-scott deleted the v2.0.remove-unnecessary-inheritance.0 branch May 16, 2016 21:35
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.

3 participants