-
Notifications
You must be signed in to change notification settings - Fork 899
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
Implement SLIP-0023 for Cardano #27152
base: master
Are you sure you want to change the base?
Conversation
542f8b5
to
b039567
Compare
8d42cbd
to
a639e0a
Compare
chromium_src/third_party/boringssl/src/crypto/curve25519/curve25519.c
Outdated
Show resolved
Hide resolved
components/brave_wallet/browser/internal/hd_key_ed25519_slip23.cc
Outdated
Show resolved
Hide resolved
components/brave_wallet/browser/internal/hd_key_ed25519_slip23.cc
Outdated
Show resolved
Hide resolved
components/brave_wallet/browser/internal/hd_key_ed25519_slip23.cc
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be good to clarify what's going on here since SLIP0023 is referencing papers that aren't considered secure anymore.
|
||
OPENSSL_EXPORT int ED25519_pubkey_from_scalar(uint8_t out_public_key[32], | ||
const uint8_t scalar[32]); | ||
OPENSSL_EXPORT int ED25519_sign_with_scalar_and_prefix( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be useful to clarify when one or the other should be used here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added comment
@@ -23,6 +23,15 @@ DerivationIndex DerivationIndex::Hardened(uint32_t index) { | |||
return DerivationIndex(index, true); | |||
} | |||
|
|||
// static | |||
DerivationIndex DerivationIndex::FromRawValueForTesting(uint32_t index) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, we don't want to allow ED25519 to use non-hardened options as it will allow for that attack I investigated previously. Can you clarify what's this for then since I assume it's not for that given we just recently looked at it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not about ED25519 itself, but the way private keys / scalars are hierarchically generated. For SLIP10 it is not possible to do normal derivations, but for SLIP23 it is.
z_hmac = crypto::hmac::SignSha512(chain_code_, data); | ||
data[0] = 0x01; | ||
cc_hmac = crypto::hmac::SignSha512(chain_code_, data); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this branch something we're not supposed to support according to SLIP10? That seems it was the way that we avoided any concerns for the paper that's broken and referenced in SLIP0023 (see here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SLIP10 does not support normal derivations but SLIP23 does
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chromium_src
lgtm. I don't see any other good way of implementing custom ed25519 sign without exposing static
internals of boringssl
.
#include "src/third_party/boringssl/src/crypto/curve25519/curve25519.c" | ||
|
||
#ifdef UNSAFE_BUFFERS_BUILD | ||
#pragma allow_unsafe_buffers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this necessary? I assume src/third_party/boringssl/src/crypto/curve25519/curve25519.c
either has this already or is built without unsafe buffers feature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These lines trigger error otherwise:
(scalar[31] & 0b11000000) == 0b01000000;
sc_muladd(out_sig + 32, hram, scalar, nonce);
Chromium turns off checks for almost whole third_party
https://source.chromium.org/chromium/chromium/src/+/main:build/config/unsafe_buffers_paths.txt;l=67-68 but it is enabled for brave/chromium_src/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this is a new file, please do not introduce unsafe buffers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted this file to be consistent with chromium one so didn't split out_sig
into two parts and didn't add tempting refactoring.
Alos it seems to me
brave/chromium_src/third_party/boringssl/
src/third_party/boringssl/
and in general
brave/chromium_src/something
src/something
the first ones should follow upstream for unsafe buffer checks policy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think consistency is an issue here, as most things are being migrated gradually, however I'm now wondering //third_party/boringssl
can depend on //base
. Better leave it as you did it, as this is shadowing a .c
file for now anyway.
// https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5 | ||
// requires scalar to follow this requirements 'The lowest 3 bits of the first | ||
// octet are cleared, the highest bit of the last octet is cleared, and the | ||
// second highest bit of the last octet is set'. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These comments should be on the header file IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to header
/* Copyright (c) 2025 The Brave Authors. All rights reserved. | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this file, | ||
* You can obtain one at https://mozilla.org/MPL/2.0/. */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The upstream file seems to be:
third_party/boringssl/src/crypto/curve25519/curve25519.cc
However this one is:
chromium_src/third_party/boringssl/src/crypto/curve25519/curve25519.c
Is there any particular reason to mark this as a C file, rather than do like upstream and use a C++ file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
upstream is
third_party/boringssl/src/crypto/curve25519/curve25519.c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks to @goodov for the link
https://source.chromium.org/chromium/_/boringssl/boringssl/+/5813c2c10c73d800f1b0d890a7d74ff973abbffc
This is not yet in master
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, fair enough.
int ED25519_is_scalar_pruned(const uint8_t scalar[32]) { | ||
return (scalar[0] & 0b00000111) == 0b00000000 && | ||
(scalar[31] & 0b11000000) == 0b01000000; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If possible to change this file from .c
to .cc
please spanify.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would that work having that base
already depends on boringssl
?
https://source.chromium.org/chromium/chromium/src/+/main:base/BUILD.gn;l=1510;bpv=1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Explained above, but yeah, it seems to be an obstacle. We could use std::span
, but not with the file still being a .c
in master.
int ED25519_pubkey_from_scalar(uint8_t out_public_key[32], | ||
const uint8_t scalar[32]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
int ED25519_sign_with_scalar_and_prefix(uint8_t out_sig[64], | ||
const uint8_t* message, | ||
size_t message_len, | ||
const uint8_t scalar[32], | ||
const uint8_t prefix[32], | ||
const uint8_t public_key[32]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto
return base::WrapUnique(new HDKeyEd25519Slip23( | ||
scalar, xprv_span.subspan<kSlip23ScalarSize, kSlip23PrefixSize>(), | ||
xprv_span.last<kSlip23ChainCodeSize>(), *pubkey)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use std::make_unique
here, and use the passkey idiom to have constructor only callable from inside HDKeyEd25519Slip23
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
Pretty good work... I left a few comments. |
b5ddf06
to
3679f95
Compare
public: | ||
using PassKey = base::PassKey<HDKeyEd25519Slip23>; | ||
|
||
HDKeyEd25519Slip23(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may be wrong but it looks like this default constructor is not used, and it feels like it shouldn't be here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice work!
Resolves brave/brave-browser#43201
Sec review: https://github.com/brave/reviews/issues/1840
The PR includes:
Ai = [kL]B
. Same as part of ED25519_keypair_from_seed but scalar comes from Ed25519_BIP32 algorithm instead of hashed seedprivate_key[0..31] -> SHA512 -> [scalar, prefix]
andprivate_key[32..63] -> public_key
. For ED25519_sign_with_scalar_and_prefixscalar, prefix, public_key
come from Ed25519_BIP32 algorithm@cardano-sdk/crypto
libraryReference implementations:
Submitter Checklist:
QA/Yes
orQA/No
;release-notes/include
orrelease-notes/exclude
;OS/...
) to the associated issuenpm run test -- brave_browser_tests
,npm run test -- brave_unit_tests
wikinpm run presubmit
wiki,npm run gn_check
,npm run tslint
git rebase master
(if needed)Reviewer Checklist:
gn
After-merge Checklist:
changes has landed on
Test Plan: