Skip to content

Commit c1ed5e9

Browse files
committed
feat(stronghold): support secp256k1 curve
1 parent 9bc4b22 commit c1ed5e9

File tree

2 files changed

+97
-4
lines changed

2 files changed

+97
-4
lines changed

plugins/stronghold/guest-js/index.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,72 @@ class ProcedureExecutor {
256256
}
257257
}).then((n) => Uint8Array.from(n))
258258
}
259+
260+
/**
261+
* Gets the Secp256k1Ecdsa public key of a SLIP10 private key.
262+
* @param privateKeyLocation The location of the private key. Must be the `outputLocation` of a previous call to `deriveSLIP10`.
263+
* @returns A promise resolving to the public key hex string.
264+
*
265+
* @since 2.1.0
266+
*/
267+
async getSecp256k1EcdsaPublicKey(privateKeyLocation: Location): Promise<Uint8Array> {
268+
return await invoke<number[]>('plugin:stronghold|execute_procedure', {
269+
...this.procedureArgs,
270+
procedure: {
271+
type: 'PublicKey',
272+
payload: {
273+
type: 'Secp256k1Ecdsa',
274+
privateKey: privateKeyLocation
275+
}
276+
}
277+
}).then((n) => Uint8Array.from(n))
278+
}
279+
280+
/**
281+
* Gets the EVM address of a SLIP10 private key.
282+
* @param privateKeyLocation The location of the private key. Must be the `outputLocation` of a previous call to `deriveSLIP10`.
283+
* @returns A promise resolving to the EVM address
284+
*
285+
* @since 2.1.0
286+
*/
287+
async getSecp256k1EcdsaEvmAddress(privateKeyLocation: Location): Promise<Uint8Array> {
288+
return await invoke<number[]>('plugin:stronghold|execute_procedure', {
289+
...this.procedureArgs,
290+
procedure: {
291+
type: 'GetEvmAddress',
292+
payload: {
293+
privateKey: privateKeyLocation
294+
}
295+
}
296+
}).then((n) => Uint8Array.from(n))
297+
}
298+
299+
/**
300+
* Creates a Secp256k1Ecdsa signature from a private key.
301+
* @param flavor The hash type
302+
* @param privateKeyLocation The location of the record where the private key is stored. Must be the `outputLocation` of a previous call to `deriveSLIP10`.
303+
* @param msg The message to sign.
304+
* @returns A promise resolving to the signature hex string.
305+
*
306+
* @since 2.1.0
307+
*/
308+
async signSecp256k1Ecdsa(
309+
flavor: 'Keccak256' | 'Sha256',
310+
privateKeyLocation: Location,
311+
msg: string
312+
): Promise<Uint8Array> {
313+
return await invoke<number[]>('plugin:stronghold|execute_procedure', {
314+
...this.procedureArgs,
315+
procedure: {
316+
type: 'Secp256k1EcdsaSign',
317+
payload: {
318+
flavor,
319+
privateKey: privateKeyLocation,
320+
msg
321+
}
322+
}
323+
}).then((n) => Uint8Array.from(n))
324+
}
259325
}
260326

261327
export class Client {

plugins/stronghold/src/lib.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ use std::{
2020
use crypto::keys::bip39;
2121
use iota_stronghold::{
2222
procedures::{
23-
BIP39Generate, BIP39Recover, Curve, Ed25519Sign, KeyType as StrongholdKeyType,
24-
MnemonicLanguage, PublicKey, Slip10Derive, Slip10DeriveInput, Slip10Generate,
25-
StrongholdProcedure,
23+
BIP39Generate, BIP39Recover, Curve, Ed25519Sign, GetEvmAddress,
24+
KeyType as StrongholdKeyType, MnemonicLanguage, PublicKey, Secp256k1EcdsaFlavor,
25+
Secp256k1EcdsaSign, Slip10Derive, Slip10DeriveInput, Slip10Generate, StrongholdProcedure,
2626
},
2727
Client, Location,
2828
};
@@ -107,13 +107,15 @@ impl From<Slip10DeriveInputDto> for Slip10DeriveInput {
107107
pub enum KeyType {
108108
Ed25519,
109109
X25519,
110+
Secp256k1Ecdsa,
110111
}
111112

112113
impl From<KeyType> for StrongholdKeyType {
113114
fn from(ty: KeyType) -> StrongholdKeyType {
114115
match ty {
115116
KeyType::Ed25519 => StrongholdKeyType::Ed25519,
116117
KeyType::X25519 => StrongholdKeyType::X25519,
118+
KeyType::Secp256k1Ecdsa => StrongholdKeyType::Secp256k1Ecdsa,
117119
}
118120
}
119121
}
@@ -129,7 +131,7 @@ impl<'de> Deserialize<'de> for KeyType {
129131
type Value = KeyType;
130132

131133
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
132-
formatter.write_str("ed25519 or x25519")
134+
formatter.write_str("ed25519, x25519, or secp256k1_ecdsa")
133135
}
134136

135137
fn visit_str<E>(self, value: &str) -> std::result::Result<Self::Value, E>
@@ -139,6 +141,7 @@ impl<'de> Deserialize<'de> for KeyType {
139141
match value.to_lowercase().as_str() {
140142
"ed25519" => Ok(KeyType::Ed25519),
141143
"x25519" => Ok(KeyType::X25519),
144+
"secp256k1_ecdsa" => Ok(KeyType::Secp256k1Ecdsa),
142145
_ => Err(serde::de::Error::custom("unknown key type")),
143146
}
144147
}
@@ -182,6 +185,16 @@ enum ProcedureDto {
182185
private_key: LocationDto,
183186
msg: String,
184187
},
188+
GetEvmAddress {
189+
#[serde(rename = "privateKey")]
190+
private_key: LocationDto,
191+
},
192+
Secp256k1EcdsaSign {
193+
flavor: Secp256k1EcdsaFlavor,
194+
#[serde(rename = "privateKey")]
195+
private_key: LocationDto,
196+
msg: String,
197+
},
185198
}
186199

187200
impl From<ProcedureDto> for StrongholdProcedure {
@@ -231,6 +244,20 @@ impl From<ProcedureDto> for StrongholdProcedure {
231244
msg: msg.as_bytes().to_vec(),
232245
})
233246
}
247+
ProcedureDto::GetEvmAddress { private_key } => {
248+
StrongholdProcedure::GetEvmAddress(GetEvmAddress {
249+
private_key: private_key.into(),
250+
})
251+
}
252+
ProcedureDto::Secp256k1EcdsaSign {
253+
flavor,
254+
private_key,
255+
msg,
256+
} => StrongholdProcedure::Secp256k1EcdsaSign(Secp256k1EcdsaSign {
257+
flavor,
258+
private_key: private_key.into(),
259+
msg: msg.as_bytes().to_vec(),
260+
}),
234261
}
235262
}
236263
}

0 commit comments

Comments
 (0)