-
Notifications
You must be signed in to change notification settings - Fork 11.4k
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
crypto: Rederive pubkey for encode/decode #6989
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
crates/sui-types/src/crypto.rs
Outdated
@@ -136,61 +136,56 @@ impl FromStr for SuiKeyPair { | |||
} | |||
|
|||
impl EncodeDecodeBase64 for SuiKeyPair { | |||
/// Encode a SuiKeyPair as `flag || pubkey || privkey` in Base64. The pubkey bytesare derived directly from privkey. |
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.
bytes _ are
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.
Also, do we want for the base64 to have flag || pubkey || privkey
or flag || privkey
and then rederive the pub key as we do in the rest of serializers?
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 understand base64 is mostly for external UX, so I'm happy with both decisions, but we should document it properly as we received some feedback re different serializers or behavior in the past.
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.
IMO its more consistent to keep it flag || pubkey || privkey
since the struct itself is called a keypair. As long as in our system, we read a keypair and ignores the pubkey part but to only read the privkey bytes to derive the keypair, i think its safe and less confusing.
+1 lemme document this more explicitly in comments
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 depends on why we need such a serializer (cause encoding is usually used for (de)serialization). Assuming each receiver of the encoded format wants to deserialize the key pair into internal structs, then we should promote secure deserialization by rederiving the pub part for better hygiene, especially sensitive object types.
Re the argument "since the struct is called keypair": there are many types across programming languages that their serialized bytes are compressed for a reason (security or bandwidth). I'd only buy the use case of compatibility with other (ie JS) libs to allow for quick conversion without rederivation, but still, IMO it's better to provide a tool to rederive Vs encoding 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.
revised.
1b7906b
to
8c4a678
Compare
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 work affected by the recent changes in fastcrypto + conflicts re serialization api changes?
rebased. |
crates/sui-types/src/crypto.rs
Outdated
} | ||
} | ||
Base64::encode(&bytes[..]) | ||
} | ||
|
||
/// Decode a SuiKeyPair from Base64 encoded `flag || privkey || pubkey` in Base64. Use the privkey bytes only to derive the pubkey and the full keypair instead of using the pubkey bytes. | ||
fn decode_base64(value: &str) -> Result<Self, eyre::Report> { | ||
let bytes = Base64::decode(value).map_err(|e| eyre::eyre!("{}", e.to_string()))?; | ||
match bytes.first() { | ||
Some(x) => { |
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.
wouldn't something like
match bytes.first() { Some(Ed25519SuiSignature::SCHEME.flag()) => ....
work 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.
simplified this part a bit
24664c4
to
a694f43
Compare
worker-key-pair: | ||
value: AB8qeQGoQuTTYjvGHOHBcX0udo4P1y34NBr1ZhW5FvA4fsz863qJR38mPjuvloaZBE4vbibFPgrwQXUa+OGTTNM= | ||
value: AH7M/Ot6iUd/Jj47r5aGmQROL24mxT4K8EF1Gvjhk0zT |
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.
this is used for swarm test only
#6940
What
This changes the serialization of a
SuiKeyPair
from base64 encodedflag || pubkey || privkey
toflag || privkey
.Why
This is to never trust the pubkey bytes inputs when but to always derive it directly from privkey when bootstrapping from read/write from files.
Notes for breaking change
If you have existing keys in sui.keystore, add new keys will throw error because the old serialization cannot be parsed anymore.
How to Fix
If you are ok with wiping the keys,
rm ~/.sui/sui_config/sui.keystore
and thensui client new-address
should work again and new keys are formatted with only private key.If you would like to keep the existing keys, you will need to convert them manually. Here is a manual python script:
To check if the conversion works, all keys should be of length 33 regardless of the the signature scheme flag.
Test