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: add message signing #40

Merged
merged 4 commits into from
Nov 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]

### Added
- added message signing features ([#40])
- implement v2 Transactions ([#27])
- added VendorField display support ([#29])
- added build options and documentation ([#32])
Expand All @@ -22,4 +23,5 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
[#27]: https://github.com/ArkEcosystem/ledger/pull/27
[#29]: https://github.com/ArkEcosystem/ledger/pull/29
[#32]: https://github.com/ArkEcosystem/ledger/pull/32
[#40]: https://github.com/ArkEcosystem/ledger/pull/40
[unreleased]: https://github.com/ArkEcosystem/ledger/compare/master...develop
20 changes: 20 additions & 0 deletions docs/payloads.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,26 @@ python examples/example_helper.py --tx ff02170100000009000300000000000000039d974

python examples/example_helper.py --tx ff0217010000000a000300000000000000037fc2e14f626586722a4f9e00dca2efbc4ac409c1ca63bc4309f56184265f95d5000000000000000000c62bd36c162dd0116a08bf8a75cd6d1f83b8f5f1e17e89c8231ebb7af595f64d

---

## Message Signing

### Length = 55

python examples/example_helper.py --message 57686174207765206b6e6f7720697320612064726f702c207768617420776520646f6e2774206b6e6f7720697320616e206f6365616e2e

### Length = 90

python examples/example_helper.py --message 57652063616e206f6e6c792073656520612073686f72742064697374616e63652061686561642c206275742077652063616e2073656520706c656e74792074686572652074686174206e6565647320746f20626520646f6e652e

### Length = 137

python examples/example_helper.py --message 54686520736369656e7469737473206f6620746f646179207468696e6b20646565706c7920696e7374656164206f6620636c6561726c792e204f6e65206d7573742062652073616e6520746f207468696e6b20636c6561726c792c20627574206f6e652063616e207468696e6b20646565706c7920616e6420626520717569746520696e73616e652e

### Length = 236

python examples/example_helper.py --message 416c6c2070617274732073686f756c6420676f20746f67657468657220776974686f757420666f7263696e672e20596f75206d7573742072656d656d62657220746861742074686520706172747320796f7520617265207265617373656d626c696e67207765726520646973617373656d626c656420627920796f752e205468657265666f72652c20696620796f752063616e277420676574207468656d20746f67657468657220616761696e2c207468657265206d757374206265206120726561736f6e2e20427920616c6c206d65616e732c20646f206e6f742075736520612068616d6d65722e


<!-- ### Type 2 Delegate Registration

Expand Down
2 changes: 0 additions & 2 deletions docs/unimplemented/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ They're not final or guaranteed as working, but should hopefully make implementi

## What's currently here

- Message Signing
- VendorField
- Type 2: Delegate Registration
- Type 4: MultiSignature Registration
- Type 6: MultiPayment
Expand Down
87 changes: 0 additions & 87 deletions docs/unimplemented/message/message.h

This file was deleted.

2 changes: 1 addition & 1 deletion docs/unimplemented/type_2/type_2.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

#include "constants.h"

#include "transactions/status.h"
#include "operations/status.h"

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Expand Down
1 change: 1 addition & 0 deletions examples/all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ echo Running all ARK Ledger Examples..
echo ""
sh ${TEST_DIR}/legacy.sh
sh ${TEST_DIR}/v2.sh
sh ${TEST_DIR}/message.sh
echo ""
92 changes: 74 additions & 18 deletions examples/example_helper.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,38 @@
# /*******************************************************************************
# * Ark Wallet
# * (c) 2017 Ledger
# * (c) ARK Ecosystem
# *
# * Licensed under the Apache License, Version 2.0 (the "License");
# * you may not use this file except in compliance with the License.
# * You may obtain a copy of the License at
# *
# * http://www.apache.org/licenses/LICENSE-2.0
# *
# * Unless required by applicable law or agreed to in writing, software
# * distributed under the License is distributed on an "AS IS" BASIS,
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# * See the License for the specific language governing permissions and
# * limitations under the License.
# ********************************************************************************/

from ledgerblue.comm import getDongle
from ledgerblue.commException import CommException
import argparse
import struct

chunkSize = 255
payloadMax = 2 * chunkSize


# Packs the BIP32 Path.
def parse_bip32_path(path):
if len(path) == 0:
return ""
result = ""
elements = path.split('/')

result = ""
elements = path.split('/')

for pathElement in elements:
element = pathElement.split('\'')
if len(element) == 1:
Expand All @@ -16,39 +41,70 @@ def parse_bip32_path(path):
result = result + struct.pack(">I", 0x80000000 | int(element[0]))
return result


# Parse Helper Arguments.
parser = argparse.ArgumentParser()
parser.add_argument('--path', help="BIP 32 path to sign with")
parser.add_argument('--message', help="Message to sign, hex encoded")
parser.add_argument('--tx', help="TX to sign, hex encoded")
args = parser.parse_args()

if args.path == None:

# Use default path if not provided.
if args.path is None:
args.path="44'/111'/0'/0/0"
if args.tx == None:
raise Exception("Missing TX")

args.tx = args.tx.decode('hex')

# Check that one and only one payload operation is called.
if args.tx is None and args.message is None or \
args.tx is not None and args.message is not None:
raise Exception("Missing or Invalid Payload")


# Set the payload
if args.message is not None:
payload = args.message.decode('hex')
operation = "08"
elif args.tx is not None:
payload = args.tx.decode('hex')
operation = "04"


# Check that the payload is not larger than the current max.
if len(payload) > payloadMax:
raise Exception('Payload size:', len(payload),
'exceeds max length:', payloadMax)


# Set the BIP32 Path.
donglePath = parse_bip32_path(args.path)


# Set the full paths length.
pathLength = len(donglePath) + 1
if len(args.tx) > 255 - pathLength:
data1 = args.tx[0 : 255 - pathLength]
data2 = args.tx[255 - pathLength:]

# Pack the payload.
if len(payload) > chunkSize - pathLength:
chunk1 = payload[0 : chunkSize - pathLength]
chunk2 = payload[chunkSize - pathLength:]
p1 = "00"
else:
data1 = args.tx
data2 = None
chunk1 = payload
chunk2 = None
p1 = "80"

apdu = ("e004" + p1 + "40").decode('hex') + chr(pathLength + len(data1)) + chr(len(donglePath) / 4) + donglePath + data1

# Build the APDU Payload
apdu = ("e0" + operation + p1 + "40").decode('hex') \
+ chr(pathLength + len(chunk1)) + chr(len(donglePath) / 4) \
+ donglePath \
+ chunk1

dongle = getDongle(True)
result = dongle.exchange(bytes(apdu))

if data2 != None:
apdu = "e0048140".decode('hex') + chr(len(data2)) + data2
result = dongle.exchange(bytes(apdu))

#result = dongle.exchange(bytes("e0040040a0058000002c80000090800000008000000000000000000b207900039f97d5a32fa1a1a0e12920f5ed21fde918a11ebf14cd42b70b4cc3633b027fcf175fa2a273f5a34d65710e67fc2b4bfe50d0d8140a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e9a435000000008096980000000000".decode('hex')))
# result = dongle.exchange(bytes("e002004096058000002c80000090800000008000000000000000".decode('hex')))
#print "publicKey " + str(result).encode('hex')
# Send second data chunk if present
if chunk2 is not None:
apdu = "e0" + operation + "8140".decode('hex') + chr(len(chunk2)) + chunk2
result = dongle.exchange(bytes(apdu))
39 changes: 39 additions & 0 deletions examples/message.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bash

echo "Message Examples"

echo ""
echo "Testing a Message Signing Operation | len = 55."
echo ""
echo "\"What we know is a drop, what we don't know is an ocean.\""
echo "> \"57686174207765206b6e6f7720697320612064726f702c207768617420776520646f6e2774206b6e6f7720697320616e206f6365616e2e\""
echo ""
python $(dirname $0)/example_helper.py --message 57686174207765206b6e6f7720697320612064726f702c207768617420776520646f6e2774206b6e6f7720697320616e206f6365616e2e
echo ""

echo ""
echo "Testing a Message Signing Operation | len = 90."
echo ""
echo "\"We can only see a short distance ahead, but we can see plenty there that needs to be done.\""
echo "> \"57652063616e206f6e6c792073656520612073686f72742064697374616e63652061686561642c206275742077652063616e2073656520706c656e74792074686572652074686174206e6565647320746f20626520646f6e652e\""
echo ""
python $(dirname $0)/example_helper.py --message 57652063616e206f6e6c792073656520612073686f72742064697374616e63652061686561642c206275742077652063616e2073656520706c656e74792074686572652074686174206e6565647320746f20626520646f6e652e
echo ""

echo ""
echo "Testing a Message Signing Operation | len = 137."
echo ""
echo "\"The scientists of today think deeply instead of clearly. One must be sane to think clearly, but one can think deeply and be quite insane.\""
echo "> \"54686520736369656e7469737473206f6620746f646179207468696e6b20646565706c7920696e7374656164206f6620636c6561726c792e204f6e65206d7573742062652073616e6520746f207468696e6b20636c6561726c792c20627574206f6e652063616e207468696e6b20646565706c7920616e6420626520717569746520696e73616e652e\""
echo ""
python $(dirname $0)/example_helper.py --message 54686520736369656e7469737473206f6620746f646179207468696e6b20646565706c7920696e7374656164206f6620636c6561726c792e204f6e65206d7573742062652073616e6520746f207468696e6b20636c6561726c792c20627574206f6e652063616e207468696e6b20646565706c7920616e6420626520717569746520696e73616e652e
echo ""

echo ""
echo "Testing a Message Signing Operation | len = 236."
echo ""
echo "\"All parts should go together without forcing. You must remember that the parts you are reassembling were disassembled by you. Therefore, if you can't get them together again, there must be a reason. By all means, do not use a hammer.\""
echo "> \"416c6c2070617274732073686f756c6420676f20746f67657468657220776974686f757420666f7263696e672e20596f75206d7573742072656d656d62657220746861742074686520706172747320796f7520617265207265617373656d626c696e67207765726520646973617373656d626c656420627920796f752e205468657265666f72652c20696620796f752063616e277420676574207468656d20746f67657468657220616761696e2c207468657265206d757374206265206120726561736f6e2e20427920616c6c206d65616e732c20646f206e6f742075736520612068616d6d65722e\""
echo ""
python $(dirname $0)/example_helper.py --message 416c6c2070617274732073686f756c6420676f20746f67657468657220776974686f757420666f7263696e672e20596f75206d7573742072656d656d62657220746861742074686520706172747320796f7520617265207265617373656d626c696e67207765726520646973617373656d626c656420627920796f752e205468657265666f72652c20696620796f752063616e277420676574207468656d20746f67657468657220616761696e2c207468657265206d757374206265206120726561736f6e2e20427920616c6c206d65616e732c20646f206e6f742075736520612068616d6d65722e
echo ""
5 changes: 3 additions & 2 deletions src/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
////////////////////////////////////////////////////////////////////////////////

// General
#define MAX_RAW_OPERATION 300U
#define MAX_RAW_OPERATION 300U
#define MAX_DISPLAY_BUFFER 255U

////////////////////////////////////////////////////////////////////////////////

Expand All @@ -43,7 +44,7 @@
#define TOKEN_DECIMALS 8U
#define TOKEN_NAME "ARK "
#define TOKEN_NAME_LENGTH 4U
#define TOKEN_NETWORK_BYTE 0x1e // ARK Mainnet
#define TOKEN_NETWORK_BYTE 0x1e // ARK Mainnet

////////////////////////////////////////////////////////////////////////////////

Expand Down
8 changes: 8 additions & 0 deletions src/operations.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "crypto/signing.h"
#include "utils/base58.h"

#include "operations/message_op.h"
#include "operations/transaction_op.h"

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -66,6 +67,7 @@

#define INS_GET_PUBLIC_KEY 0x02
#define INS_SIGN 0x04
#define INS_SIGN_MESSAGE 0x08
#define INS_GET_APP_CONFIGURATION 0x06

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -200,6 +202,7 @@ static void handleSigningContext() {
os_memmove(&tmpCtx.signing.data[tmpCtx.signing.dataLength],
workBuffer,
dataLength);

tmpCtx.signing.dataLength += dataLength;
}

Expand Down Expand Up @@ -235,6 +238,11 @@ void handleOperation(volatile unsigned int *flags, volatile unsigned int *tx) {
handleTransaction(tmpCtx.signing.data, tmpCtx.signing.dataLength);
break;

case INS_SIGN_MESSAGE:
handleSigningContext();
handleMessage(tmpCtx.signing.data, tmpCtx.signing.dataLength);
break;

case INS_GET_APP_CONFIGURATION: handleAppConfiguration(tx); break;

default: THROW(0x6D00);
Expand Down
Loading