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

feat: HMAC support in Crypto APIs #43536

Merged
merged 1 commit into from
Dec 3, 2020
Merged

Conversation

jonbonazza
Copy link
Contributor

@jonbonazza jonbonazza commented Nov 14, 2020

fixes: godotengine/godot-proposals#1098

Couple different ways to use this. The more low level approach (especially useful for HMACing streamed content:

extends Node

var hmac = HMACContext.new()

func _ready():
	var key = "supersecretkey" # Key can be of any size greater than 0.
	var data = "Return of the MAC!" # Data size can be any size greater than 0 as well.
	hmac.start(HashingContext.HASH_SHA256, key.to_utf8())
	hmac.update(data.to_utf8())
	var digest = hmac.finish()
        print_hex(digest)

Or the more high level approach that is going to be most useful 99% of the time:

extends Node

var crypto = Crypto.new()

func _ready():
    var key = "supersecretkey" # Key can be of any size greater than 0.
    var data = "Return of the MAC!" # Data size can be any size greater than 0 as well.
    var digest = crypto.hmac_digest(HashingContext.HASH_SHA256, key.to_utf8(), data.to_utf8())
    print_hex(digest)

I've also provided a convenience function for comparing two HMAC digests in a way that is impervious to timing attacks:

extends Node

var crypto = Crypto.new()

func _ready():
    var hm1 # PackedByteArray containing an HMACdigest
    var hm2 # PackedByteArray containing a second HMAC digest
    var equal = crypto.hmac_equals(hm1, hm2)
    print(equal)

@jonbonazza jonbonazza requested review from a team as code owners November 14, 2020 14:16
@jonbonazza
Copy link
Contributor Author

Needs some testing still before merge but this is the general approach I am going for @Faless

@jonbonazza jonbonazza force-pushed the hmac branch 4 times, most recently from ab0433b to 65c5d7b Compare November 14, 2020 14:50
@Calinou Calinou added this to the 4.0 milestone Nov 14, 2020
Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

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

Some stylistic changes for documentation.

doc/classes/Crypto.xml Outdated Show resolved Hide resolved
doc/classes/Crypto.xml Outdated Show resolved Hide resolved
doc/classes/HMACContext.xml Outdated Show resolved Hide resolved
doc/classes/HMACContext.xml Outdated Show resolved Hide resolved
@jonbonazza
Copy link
Contributor Author

@Calinou thanks. I'm going through and trying to address all of the static check issues from CI. Once that's done, I'll accept your suggestions.

@jonbonazza jonbonazza force-pushed the hmac branch 3 times, most recently from c623c7e to 362efe2 Compare November 14, 2020 15:36
@fire
Copy link
Member

fire commented Nov 14, 2020

Can you provide a test project? It'll make testing faster.

@jonbonazza
Copy link
Contributor Author

@fire yep i def plan to. Still need to do some testing myself though as mentioned above. Pulled an all nighter to implement this though, so ill do so after i rest a bit more haha

@jonbonazza jonbonazza force-pushed the hmac branch 6 times, most recently from a1ee02e to 7d9c84d Compare November 15, 2020 06:02
@jonbonazza
Copy link
Contributor Author

@fire I opted instead to create unit tests for everything. If you feel an example project is still useful, I can whip one together though. let me know.

@jonbonazza
Copy link
Contributor Author

@akien-mga @Faless oh cool. Ill work on adding thise soon then

@jonbonazza jonbonazza force-pushed the hmac branch 12 times, most recently from 5492de7 to 38cc3f7 Compare November 22, 2020 06:50
@jonbonazza
Copy link
Contributor Author

@Calinou @akien-mga @Faless this is ready again for y'all.

core/crypto/crypto.cpp Outdated Show resolved Hide resolved
core/crypto/crypto.cpp Outdated Show resolved Hide resolved
core/crypto/crypto.h Outdated Show resolved Hide resolved
core/crypto/crypto_core.h Outdated Show resolved Hide resolved
doc/classes/Crypto.xml Show resolved Hide resolved
modules/mbedtls/crypto_mbedtls.cpp Outdated Show resolved Hide resolved
modules/mbedtls/crypto_mbedtls.cpp Outdated Show resolved Hide resolved
modules/mbedtls/crypto_mbedtls.cpp Show resolved Hide resolved
modules/mbedtls/crypto_mbedtls.cpp Show resolved Hide resolved
modules/mbedtls/crypto_mbedtls.cpp Outdated Show resolved Hide resolved
print(hmac.hex_encode())

[/gdscript]
[csharp]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Calinou @akien-mga I'm not super familiar with Godot's C# jazz. Mind checking my work here?

@jonbonazza jonbonazza force-pushed the hmac branch 2 times, most recently from 0c80d36 to 84f7009 Compare November 24, 2020 10:38
@jonbonazza
Copy link
Contributor Author

@Faless I've addressed all of your feedback. This is ready for you again. :)

Copy link
Collaborator

@Faless Faless left a comment

Choose a reason for hiding this comment

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

See my comments

modules/mbedtls/crypto_mbedtls.cpp Outdated Show resolved Hide resolved
modules/mbedtls/crypto_mbedtls.cpp Outdated Show resolved Hide resolved
modules/mbedtls/crypto_mbedtls.cpp Outdated Show resolved Hide resolved
@@ -90,6 +125,8 @@ void Crypto::_bind_methods() {
ClassDB::bind_method(D_METHOD("verify", "hash_type", "hash", "signature", "key"), &Crypto::verify);
ClassDB::bind_method(D_METHOD("encrypt", "key", "plaintext"), &Crypto::encrypt);
ClassDB::bind_method(D_METHOD("decrypt", "key", "ciphertext"), &Crypto::decrypt);
ClassDB::bind_method(D_METHOD("hmac_digest", "hash_type", "key", "msg"), &Crypto::hmac_digest);
ClassDB::bind_method(D_METHOD("constant_time_compare", "hm1", "hm2"), &Crypto::constant_time_compare);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I was wondering if we should rename the parameters to something more sensible. Would byte_array/other_byte_array make sense?
There is also the case where the 2 sizes do not match, so a timing attack could still successfully discover the size of the compared value.
Would it make sense to call the first parameter trusted_bytes and the second one received_bytes, so we can, in the future maybe, improve it knowing which one the user consider trusted (which I think is how safe_memcmps work, but I'm no expert, so the function is fine for now).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I renamed the parameters for the function. I didn't do anything about the size comparison shortcut though, as we discussed on IRC.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It seems you changed the name of the function parameters, not the one in the method_bind (which are the names used by the doc generation tool).
rename hm1 and hm2 in bind_method to: trusted, received.
Possibly rename trusted, received in the method definition to p_trusted, p_received.

Copy link
Collaborator

Choose a reason for hiding this comment

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

And remember to re-run the doctool to update the XML

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Faless done. Let me know if you see anything else. Thanks!

@jonbonazza
Copy link
Contributor Author

Ready again for you @Faless

Copy link
Collaborator

@Faless Faless left a comment

Choose a reason for hiding this comment

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

Almost ready. See my comment about the parameter renames.
Looks good otherwise.
Not sure if the @godotengine/documentation team has some other remarks.
Please remember to squash your commits afterwards: https://docs.godotengine.org/en/stable/community/contributing/pr_workflow.html#the-interactive-rebase

Copy link
Collaborator

@Faless Faless left a comment

Choose a reason for hiding this comment

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

Great work! 🥇

@Faless Faless merged commit 502ff74 into godotengine:master Dec 3, 2020
@Faless
Copy link
Collaborator

Faless commented Dec 3, 2020

Thanks!

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.

Expose HMAC to GDScript
5 participants