Skip to content

Commit

Permalink
Adapt client/swiss-knife to new signing & verification API
Browse files Browse the repository at this point in the history
Closes: aptos-labs#4846
Approved by: ankushagarwal
huitseeker authored and bors-libra committed Jul 7, 2020
1 parent 32cbcc7 commit a70f718
Showing 5 changed files with 139 additions and 45 deletions.
29 changes: 24 additions & 5 deletions client/swiss-knife/README.md
Original file line number Diff line number Diff line change
@@ -20,11 +20,11 @@ The `sample_inputs` folder contains a list of sample json inputs for various ope
# For the txn_params json schema, look at the `struct TxnParams`
# For the script_params json schema, look at the `struct MoveScriptParams`
$ cargo run -p swiss-knife -- generate-raw-txn < sample_inputs/generate_raw_txn_peer_to_peer_transfer.json
{
"error_message": "",
"data": {
"raw_txn": "e1b3d22871989e9fd9dc6814b2f4fc412a0000000000000001ed01a11ceb0b01000701000202020403061004160205181d07356f08a4011000000001010000020001000003020301010004010300010501060c0108000506080005030a020a020005060c05030a020a020109000c4c696272614163636f756e741257697468647261774361706162696c6974791b657874726163745f77697468647261775f6361706162696c697479167061795f66726f6d5f776974685f6d657461646174611b726573746f72655f77697468647261775f6361706162696c69747900000000000000000000000000000001010104010c0b0011000c050e050a010a020b030b0438000b05110202010700000000000000000000000000000001034c4252034c425200040371e931795d23e9634fd24a5992065f6b0164000000000000000400040040420f00000000000000000000000000034c4252fc24f65e00000000",
"raw_txn_hash": "a293a4b658d76bea6c07f3cf064b243f7a4f1087054ce1072029c148d1ab3a42"
}
}
@@ -40,11 +40,11 @@ $ cargo run -p swiss-knife -- generate-signed-txn < sample_inputs/generate_signe
# Generate a preburn raw transaction (https://github.com/libra/libra/blob/1f86705b/language/transaction-builder/src/generated.rs#L480)
$ cargo run -p swiss-knife -- generate-raw-txn < sample_inputs/generate_raw_txn_preburn.json
{
"error_message": "",
"data": {
"raw_txn": "e1b3d22871989e9fd9dc6814b2f4fc412a00000000000000018602a11ceb0b010007010004020409030d1604230405272107487708bf011000000001000001010101030100000200010101010402030001050301000106040501010307000702060c0b000109000001060c0108010206080103010b0001090002060c03010900054c696272610c4c696272614163636f756e740a7072656275726e5f746f1257697468647261774361706162696c6974791b657874726163745f77697468647261775f6361706162696c6974791b726573746f72655f77697468647261775f6361706162696c6974790d77697468647261775f66726f6d00000000000000000000000000000001010106030b0a0011010c020b000e020a01380038010b02110202010700000000000000000000000000000001034c4252034c4252000101640000000000000040420f00000000000000000000000000034c4252fc24f65e00000000",
"raw_txn_hash": "5f1256d71f183f15de24ad80c96f77919c8c1ff97cab0727d10f7b8367a9b1ec"
"raw_txn": "e1b3d22871989e9fd9dc6814b2f4fc412a0000000000000001d401a11ceb0b0100000007010002020204030610041602051815072d60088d011000000001010000020001000003020301010004010300010501060c01080003060c060800030002060c030109000c4c696272614163636f756e741257697468647261774361706162696c6974791b657874726163745f77697468647261775f6361706162696c697479077072656275726e1b726573746f72655f77697468647261775f6361706162696c69747900000000000000000000000000000001010104010a0a0011000c020b000e020a0138000b02110202010700000000000000000000000000000001034c4252034c4252000101640000000000000040420f00000000000000000000000000034c4252fc24f65e00000000"
}
}
@@ -95,10 +95,10 @@ $ cargo run -p swiss-knife -- generate-test-ed25519-keypair --seed 0
}
```

## Sign a payload using a Ed25519 Private Key
## Sign a transaction using a Ed25519 Private Key

```shell script
$ cargo run -p swiss-knife -- sign-payload-using-ed25519 < sample_inputs/sign_payload.json
$ cargo run -p swiss-knife -- sign-transaction-using-ed25519 < sample_inputs/generated_raw_txn_p2p_transfer.json

{
"error_message": "",
@@ -108,6 +108,20 @@ $ cargo run -p swiss-knife -- sign-payload-using-ed25519 < sample_inputs/sign_pa
}
```

## Verify a transaction signature using a Ed25519 Public Key

```shell script
$ cargo run -p swiss-knife -- verify-transaction-ed25519-signature < sample_inputs/generated_signed_txn_p2p_transfer.json

{
"error_message": "",
"data": {
"valid_signature": true
}
}
```


## Verify a payload signature using a Ed25519 Public Key

```shell script
@@ -120,3 +134,8 @@ $ cargo run -p swiss-knife -- verify-ed25519-signature < sample_inputs/verify_si
}
}
```

(Note that this is not a test of a transaction signature. This only tests the
"raw" internal Ed255519 library used in Libra, and will only allow you to
e.g. get certainty that we use Ed25519 variant 'pure' as opposed to
'pre-hashed'. For testing a transaction signature, see the previous example)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"raw_txn": "e1b3d22871989e9fd9dc6814b2f4fc412a0000000000000001e101a11ceb0b010000000701000202020403061004160205181d0735610896011000000001010000020001000003020301010004010300010501060c0108000506080005030a020a020005060c05030a020a020109000c4c696272614163636f756e741257697468647261774361706162696c6974791b657874726163745f77697468647261775f6361706162696c697479087061795f66726f6d1b726573746f72655f77697468647261775f6361706162696c69747900000000000000000000000000000001010104010c0b0011000c050e050a010a020b030b0438000b05110202010700000000000000000000000000000001034c4252034c425200040371e931795d23e9634fd24a5992065f6b0164000000000000000400040040420f00000000000000000000000000034c4252fc24f65e00000000",
"private_key": "b2f7f581d6de3c06a822fd6e7e8265fbc00f8401696a5bdc34f5a6d2ff3f922f"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"raw_txn": "e1b3d22871989e9fd9dc6814b2f4fc412a0000000000000001e101a11ceb0b010000000701000202020403061004160205181d0735610896011000000001010000020001000003020301010004010300010501060c0108000506080005030a020a020005060c05030a020a020109000c4c696272614163636f756e741257697468647261774361706162696c6974791b657874726163745f77697468647261775f6361706162696c697479087061795f66726f6d1b726573746f72655f77697468647261775f6361706162696c69747900000000000000000000000000000001010104010c0b0011000c050e050a010a020b030b0438000b05110202010700000000000000000000000000000001034c4252034c425200040371e931795d23e9634fd24a5992065f6b0164000000000000000400040040420f00000000000000000000000000034c4252fc24f65e00000000",
"signature": "838ee4290ccd683eb793eb760521d7d139ce8e770aafc11c27e39c799ed97375bc1c12fd80fd3983da66558697fcfd3fffe7fd3816dda802bd2ee671670c3802",
"public_key": "edd0f6de342a1e6a7236d6244f23d83eedfcecd059a386c85055701498e77033"
}
4 changes: 0 additions & 4 deletions client/swiss-knife/sample_inputs/sign_payload.json

This file was deleted.

142 changes: 106 additions & 36 deletions client/swiss-knife/src/main.rs
Original file line number Diff line number Diff line change
@@ -3,9 +3,8 @@

use libra_crypto::{
ed25519::{Ed25519PrivateKey, Ed25519PublicKey, Ed25519Signature},
hash::CryptoHash,
test_utils::KeyPair,
HashValue, Signature, SigningKey, Uniform, ValidCryptoMaterialStringExt,
Signature, SigningKey, Uniform, ValidCryptoMaterialStringExt,
};
use libra_types::transaction::{
authenticator::AuthenticationKey, RawTransaction, SignedTransaction, TransactionPayload,
@@ -30,10 +29,18 @@ enum Command {
#[structopt(long)]
seed: Option<u64>,
},
/// Generates a signature using the provided Ed25519 private key.
SignPayloadUsingEd25519,
/// Verifies the Ed25519 signature using the provided Ed25519 public key.
/// Verifies the Ed25519 signature using the provided Ed25519 public
/// key. Assumes the caller has a correct binary payload: this is thex
/// Ed25519 signature verification you would find in an off-the-shelf
/// Ed25519 library (RFC 8032), hence advised only for sanity-checking and
/// testing.
VerifyEd25519Signature,
/// Generates a signature of a RawTransaction using the provided Ed25519
/// private key. Handles producing the binary representation of that transaction.
SignTransactionUsingEd25519,
/// Verifies the Ed25519 signature using the provided Ed25519 public
/// key. Handles producing the binary representation of that transaction.
VerifyTransactionEd25519Signature,
}

#[derive(Debug, StructOpt)]
@@ -70,23 +77,32 @@ fn main() {
Command::GenerateTestEd25519Keypair { seed } => {
helpers::exit_success_with_data(generate_key_pair(seed));
}
Command::SignPayloadUsingEd25519 => {
Command::VerifyEd25519Signature => {
let input = helpers::read_stdin();
let request: SignPayloadUsingEd25519Request = serde_json::from_str(&input)
let request: VerifyEd25519SignatureRequest = serde_json::from_str(&input)
.map_err(|err| {
helpers::exit_with_error(format!("Failed to deserialize json : {}", err))
})
.unwrap();
helpers::exit_success_with_data(sign_payload_using_ed25519(request));
helpers::exit_success_with_data(verify_signature_using_ed25519(request));
}
Command::VerifyEd25519Signature => {
Command::SignTransactionUsingEd25519 => {
let input = helpers::read_stdin();
let request: VerifyEd25519SignatureRequest = serde_json::from_str(&input)
let request: SignTransactionUsingEd25519Request = serde_json::from_str(&input)
.map_err(|err| {
helpers::exit_with_error(format!("Failed to deserialize json : {}", err))
})
.unwrap();
helpers::exit_success_with_data(verify_signature_using_ed25519(request));
helpers::exit_success_with_data(sign_transaction_using_ed25519(request));
}
Command::VerifyTransactionEd25519Signature => {
let input = helpers::read_stdin();
let request: VerifyTransactionEd25519SignatureRequest = serde_json::from_str(&input)
.map_err(|err| {
helpers::exit_with_error(format!("Failed to deserialize json : {}", err))
})
.unwrap();
helpers::exit_success_with_data(verify_transaction_signature_using_ed25519(request));
}
}
}
@@ -140,7 +156,6 @@ struct GenerateRawTxnRequest {
#[serde(rename_all = "snake_case")]
struct GenerateRawTxnResponse {
pub raw_txn: String,
pub raw_txn_hash: String,
}

fn generate_raw_txn(g: GenerateRawTxnRequest) -> GenerateRawTxnResponse {
@@ -187,7 +202,6 @@ fn generate_raw_txn(g: GenerateRawTxnRequest) -> GenerateRawTxnResponse {
})
.unwrap(),
),
raw_txn_hash: CryptoHash::hash(&raw_txn).to_hex(),
}
}

@@ -283,30 +297,37 @@ fn generate_key_pair(seed: Option<u64>) -> GenerateKeypairResponse {
}
}

///////////////////////////
// Sign a RawTransaction //
///////////////////////////

#[derive(Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
struct SignPayloadUsingEd25519Request {
pub payload: String,
struct SignTransactionUsingEd25519Request {
pub raw_txn: String,
pub private_key: String,
}

#[derive(Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
struct SignPayloadUsingEd25519Response {
struct SignTransactionUsingEd25519Response {
pub signature: String,
}

fn sign_payload_using_ed25519(
request: SignPayloadUsingEd25519Request,
) -> SignPayloadUsingEd25519Response {
let hash_value = HashValue::from_hex(&request.payload)
.map_err(|err| {
helpers::exit_with_error(format!(
"Failed to hex decode payload into HashValue {} : {}",
request.payload, err
))
})
.unwrap();
fn sign_transaction_using_ed25519(
request: SignTransactionUsingEd25519Request,
) -> SignTransactionUsingEd25519Response {
let raw_txn: RawTransaction = lcs::from_bytes(
&hex::decode(request.raw_txn.clone())
.map_err(|err| {
helpers::exit_with_error(format!("hex decode of raw_txn failed : {}", err))
})
.unwrap(),
)
.map_err(|err| {
helpers::exit_with_error(format!("lcs deserialization failure of raw_txn : {}", err))
})
.unwrap();
let private_key = Ed25519PrivateKey::from_encoded_string(&request.private_key)
.map_err(|err| {
helpers::exit_with_error(format!(
@@ -315,9 +336,8 @@ fn sign_payload_using_ed25519(
))
})
.unwrap();
#[allow(deprecated)]
let signature = private_key.sign_message(&hash_value);
SignPayloadUsingEd25519Response {
let signature = private_key.sign(&raw_txn);
SignTransactionUsingEd25519Response {
signature: signature
.to_encoded_string()
.map_err(|err| {
@@ -327,6 +347,10 @@ fn sign_payload_using_ed25519(
}
}

//////////////////////
// Verify raw bytes //
//////////////////////

#[derive(Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
struct VerifyEd25519SignatureRequest {
@@ -344,14 +368,61 @@ struct VerifyEd25519SignatureResponse {
fn verify_signature_using_ed25519(
request: VerifyEd25519SignatureRequest,
) -> VerifyEd25519SignatureResponse {
let hash_value = HashValue::from_hex(&request.payload)
let message = helpers::hex_decode(&request.payload);
let signature = Ed25519Signature::from_encoded_string(&request.signature)
.map_err(|err| {
helpers::exit_with_error(format!(
"Failed to hex decode payload into HashValue {} : {}",
request.payload, err
"Failed to hex decode signature {} : {}",
request.signature, err
))
})
.unwrap();
let public_key = Ed25519PublicKey::from_encoded_string(&request.public_key)
.map_err(|err| {
helpers::exit_with_error(format!(
"Failed to hex decode public_key {} : {}",
request.public_key, err
))
})
.unwrap();
let valid_signature = signature
.verify_arbitrary_msg(&message, &public_key)
.is_ok();
VerifyEd25519SignatureResponse { valid_signature }
}

//////////////////////////////////////////
// verify signature of a RawTransaction //
//////////////////////////////////////////

#[derive(Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
struct VerifyTransactionEd25519SignatureRequest {
pub raw_txn: String,
pub signature: String,
pub public_key: String,
}

#[derive(Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
struct VerifyTransactionEd25519SignatureResponse {
pub valid_signature: bool,
}

fn verify_transaction_signature_using_ed25519(
request: VerifyTransactionEd25519SignatureRequest,
) -> VerifyTransactionEd25519SignatureResponse {
let raw_txn: RawTransaction = lcs::from_bytes(
&hex::decode(request.raw_txn.clone())
.map_err(|err| {
helpers::exit_with_error(format!("hex decode of raw_txn failed : {}", err))
})
.unwrap(),
)
.map_err(|err| {
helpers::exit_with_error(format!("lcs deserialization failure of raw_txn : {}", err))
})
.unwrap();
let signature = Ed25519Signature::from_encoded_string(&request.signature)
.map_err(|err| {
helpers::exit_with_error(format!(
@@ -368,7 +439,6 @@ fn verify_signature_using_ed25519(
))
})
.unwrap();
#[allow(deprecated)]
let valid_signature = signature.verify(&hash_value, &public_key).is_ok();
VerifyEd25519SignatureResponse { valid_signature }
let valid_signature = signature.verify_struct_msg(&raw_txn, &public_key).is_ok();
VerifyTransactionEd25519SignatureResponse { valid_signature }
}

0 comments on commit a70f718

Please sign in to comment.