Coder Social home page Coder Social logo

status-keycard's Introduction

What is Keycard?

Keycard is an implementation of a BIP-32 HD wallet running on Javacard 3.0.4+ (see implementation notes)

It supports among others

Communication with the Keycard happens through a simple APDU interface, together with a Secure Channel guaranteeing confidentiality, authentication and integrity of all commands. It supports both NFC and ISO7816 physical interfaces, meaning that it is compatible with any Android phone equipped with NFC, and all USB Smartcard readers.

The most obvious case for integration of Keycard is crypto wallets (ETH, BTC, etc), however it can be used in other systems where a BIP-32 key tree is used and/or you perform authentication/identification.

Where to start?

A good place to start is our documentation site https://keycard.tech/docs/

You can also join the dicussion about this project on Status channel: https://get.status.im/chat/public/status-keycard

If you just want to use the Keycard as your hardware wallet there are currently three apps supporting it

  1. Status [Android][iOS]
  2. WallETH [Android]
  3. Enno Walet https://ennowallet.com/

How to contribute?

Anyone is welcome to contribute to Keycard!

Most of our communication about the project is going on here: https://get.status.im/chat/public/status-keycard

Should you wish to work on an issue, please claim it first by commenting on the GitHub issue that you want to work on it. This is to prevent duplicated efforts from contributors on the same issue.

How to build the project?

The project is built using Gradle with the Fidesmo Javacard Gradle plugin. You can set the JavaCard HOME not only through the environment but also creating a gradle.properties file with the property "com.fidesmo.gradle.javacard.home" set to the correct path.

Testing is done with JUnit and performed either on a real card or on jCardSim. Although the tests are comprehensive, debugging on the real card is not easy because raw APDUs are not shown in the test log and there is no way to set breakpoints in the applet.

In order to test with the simulator with an IDE, you need to pass these additional parameters to the JVM

-noverify -Dim.status.keycard.test.target=simulator

Compilation

  1. Download and install the JavaCard 3.0.4 SDK from Oracle
  2. Clone the Github repo for our fork of jCardSim
  3. Create a gradle.properties (see below for an example)
  4. Run ./gradlew convertJavacard

Installation

  1. Follow all steps from the Compilation phase (except the last one)
  2. Disconnect all card reader terminals from the system, except the one with the card where you want to install the applet
  3. Run ./gradlew install

Testing

  1. Follow all steps from the Installation phase (except the last one)
  2. Make sure your JRE has the JCE Unlimited Strength Jurisdiction Policy Files installed. For more information check here.
  3. Run ./gradlew test

What kind of smartcards can I use?

  • The applet requires JavaCard 3.0.4 (with the addition of KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY ) or later.
  • The class byte of the APDU is not checked since there are no conflicting INS code.
  • The GlobalPlatform ISD keys are set to c212e073ff8b4bbfaff4de8ab655221f.

The algorithms the card must support are at least:

  • Cipher.ALG_AES_BLOCK_128_CBC_NOPAD
  • Cipher.ALG_AES_CBC_ISO9797_M2
  • KeyAgreement.ALG_EC_SVDP_DH_PLAIN
  • KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY
  • KeyPair.ALG_EC_FP (generation of 256-bit keys)
  • MessageDigest.ALG_SHA_256
  • MessageDigest.ALG_SHA_512
  • RandomData.ALG_SECURE_RANDOM
  • Signature.ALG_AES_MAC_128_NOPAD
  • Signature.ALG_ECDSA_SHA_256

Best performance is achieved if the card supports:

  • Signature.ALG_HMAC_SHA_512

Other related repositories

Java SDK for Android and Desktop https://github.com/status-im/status-keycard-java

Swift SDK for iOS13 and above https://github.com/status-im/Keycard.swift

Keycard CLI for Desktop https://github.com/status-im/keycard-cli

status-keycard's People

Contributors

0xc1c4da avatar arachnid avatar bitgamma avatar gravityblast avatar guylouis avatar tista3 avatar x5engine avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

status-keycard's Issues

POS support

The hardwallet cannot be currently used in POS because pairing is required before usage.

There are several possible ways to overcome this with different security/usability tradeoffs and we must decide something.

The most secure way is not to change anything in the card and implement POS support in the client. The POS beams through NFC or BLE the ethereum transaction to the phone and from there the user can proceed as usual (except it might beam back the signed tx to the POS instead of submitting autonomously, so no internet connection on the device side is required). This is probably the most secure and still usable solution.

If however we want to exclude the usage of a third device. My proposal is as follows

  • define a "payment PIN" which can be used in pairless transactions and which is separate from the main pin. This PIN can be 4 digits.
  • define pairing-less key derivation paths with mechanism similar to PIN-less path. A path could even be both pairing-less and PIN-less (for example for door opening usage or for pocket money accounts).
  • allow pairing-less clients to establish a secure channel and execute operations ONLY using pairingless keys. All other card operation will be disabled and PIN verification will only work for the payment PIN.

I think this is something that will eventually be needed, because it opens the door to several usage scenarios while not really compromising on security. The UX suffers a little, since you need to remember another PIN, but for PIN-less applications this would work a treat. We could even not introduce the payment PIN and only allow PIN-less transactions using this mechanism.

Allow use as FIDO authenticator

We could implement, as a separate applet, a FIDO U2F authenticator. Ideally, if the formats are compatible, one would be able to use one of the derived keys as identity for authentification.

Drop assisted key derivation support

The assisted key derivation functionality is needed to support cards without KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY. This was implemented because no card actually implemented that and we will wanted to do BIP-32.

However, it is a workaround and it is not strictly necessary anymore. Removing it would allow removing quite a lot of code (making the applet smaller) and test cases.

Create a new SDK or development tool facilitating integration of Keycard

Title: Create a new SDK or development tool facilitating integration of Keycard

About Keycard: Keycard is an open framework for smartcards in the crypto sphere. Smartcards are cost-effective, highly secure hardware, that can generate & store private keys, sign transactions with a tap on a mobile (android sdk available), or with a desktop (with a usb reader).

Keycard can be used as a easy-to-use and mobile friendly hardware wallet, bringing security and ownership over their keys to end users. Its form factor, tangibility and cost effectiveness can also be leveraged as an adoption tool, to bring new comers to decentralized services.

  • Keycard has an Android SDK & Go SDK.
  • Keycard is integrated with geth.

Challenge description: Create a new SDK or development tool facilitating integration of Keycard in various environments.

Developer Guide: Full documentation and links to repos can be found here
https://status.im/keycard_api/

How to get a Keycard:
If you want to hack with Keycard, get in touch with us on https://get.status.im/chat/public/status-keycard, let us know what you plan to build, and we will send you a keycard!

Prize: 1,500 DAI

Status Keycard compatibles wallets ?

Hello,

What are the current wallets compatible and who have integrated the keycard as a hardware wallet?

When will be ready the first pubic version of Keycard hardware crypto wallet ?
(Compatible with all Major Cryptocurrencies, Ethereum, ERC20 tokens, Bitcoin, Bitcoin Cash, Litecoin, Ripple, ...etc.)

Simulator problems

testing with simulator fails with the stacktrace below.

java.lang.RuntimeException: Internal reflection error

        at com.licel.jcardsim.base.SimulatorRuntime.<init>(SimulatorRuntime.java:93)
        at com.licel.jcardsim.base.SimulatorRuntime.<init>(SimulatorRuntime.java:73)
        at com.licel.jcardsim.smartcardio.CardSimulator.<init>(CardSimulator.java:44)
        at im.status.keycard.KeycardTest.openSimulatorChannel(KeycardTest.java:131)
        at im.status.keycard.KeycardTest.initAll(KeycardTest.java:93)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:436)
        at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
        at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$invokeBeforeAllMethods$6(ClassTestDescriptor.java:239)
        at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
        at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.invokeBeforeAllMethods(ClassTestDescriptor.java:238)
        at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.before(ClassTestDescriptor.java:164)
        at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.before(ClassTestDescriptor.java:65)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:110)
        at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
        at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
        at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
        at java.util.Iterator.forEachRemaining(Iterator.java:116)
        at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
        at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
        at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
        at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
        at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:74)
        at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
        at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
        at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.IllegalArgumentException: wrong number of arguments
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at com.licel.jcardsim.base.SimulatorRuntime.<init>(SimulatorRuntime.java:83)
        ... 43 more

Sign with derive Wrong Data error

When calling the sign command with the "derive" option, I always get an 6A80 WRONG_DATA error. Data sent is : the hash to sign (32 bytes) | 4x32-bit integers
I guess this error is thrown by the L1261 in KeycardApplet.java. Still, I can't see what's wrong with the data I send. For example EXPORT KEY is always working fine, even with "derive" option and a path provided.

Here are some logs about the issue I'm facing :

Public Key reading (export)
Use Derive
80 c2 01 01 + 4x4 bytes for path (= m/44'/0'/0'/0)
--> sending (SCP)
80c20101108000002c800000008000000000000000
<-- received (SCP) : 9000
a1438041049caa9dc12313a0101ca0dfc35d3e87039d070e09e9da4bf2119e40d1a249194a558be3ec5a0e34eeaaef1dfd708d1bb68da1906b450343a69fbb4d750cdaeae0

Sign
Use Current
80 c0 00 00 + 32 bytes hash
--> sending (SCP)
80c000002096ee85875b737ea6dce2f892516c40af0d296112ad64b6ff1eb0ce7034c2938b
<-- received (SCP) : 9000
a08189804104f50167e9f253bbbd7613ac637111d5abda618329108fb142d5c79c82fa286f0066ad9438a37e9224fdd57f68322fbd18f1ce37cf4c51ccc5ed6f6c617dab8f3e304402206ca8cc0881a57c93a71914063bea5c152cfd29766ef6e508bb53864945ceea1f02206353f923168366d6f343aff31c8a479339764ef8f90dd18413fe70a499ccfe00

Sign
Use Derive
80 c0 01 00 + 32 bytes hash + 4x4 bytes for path (= m/44'/0'/0'/0)
--> sending (SCP)
80c001003096ee85875b737ea6dce2f892516c40af0d296112ad64b6ff1eb0ce7034c2938b8000002c800000008000000000000000
<-- received (SCP) : 6a80

Can you test on your side? What is the data format for SIGN when P1=1 ?

installation issue due to gpshell

Hello,

I'm trying to run the tests but gradlew install throws an error like this:

FAILURE: Build failed with an exception.
               
* What went wrong:
Execution failed for task ':install'.
> Process 'command 'C:\Users\test\Documents\programs\hardware-wallet\GPShell-1.4.4\GPShell.exe'' finished with non-zero exit value 1
               
* Try:         
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
               
BUILD FAILED

My gradlew.properties looks like this:

com.fidesmo.gradle.javacard.home=Java_Card_Development_Kit
im.status.gradle.gpshell=C:\\Users\\test\\Documents\\programs\\hardware-wallet\\GPShell-1.4.4\\GPShell.exe
im.status.gradle.gpshell.isd=A000000151000000
im.status.gradle.gpshell.mac_key=404142434445464748494a4b4c4d4e4f
im.status.gradle.gpshell.enc_key=404142434445464748494a4b4c4d4e4f
im.status.gradle.gpshell.kek_key=404142434445464748494a4b4c4d4e4f
im.status.gradle.gpshell.kvn=0
im.status.wallet.test.simulated=true

I tried providing the relative path as well. But it failed with same error.
Can someone plz help?

Update readme 'HOST section'

Hello,

it would be really helpful to write down compatible host apps so that the card can be really used. Now one has to search for hours an app to use the card with - if you have WallETH, say so. If you have more (I was unable to find), say so. I spent 2 hours searching for compatible hosts. Even Status app does not seem to support it.

Thanks!

[1,000 DAI] - Proof of Concept for Integration of Keycard Within Mobile or Desktop Apps

Proof of Concept for Integration of Keycard Within Mobile or Desktop Apps

"Important To participate in this bounty you'll need a physical Keycard mailed to you. Please express interest in the bounty with your project idea detailed in the work plan, and we will reach out to get your information and send you a Keycard ASAP!"

Prize Bounty

1,000 DAI

Challenge Description

Create a proof of concept integration of Keycard within mobile or desktop apps (e.g. wallets, web3 browsers) for security, dapps interaction, or payment purposes. This can include hardware enforced authorization of payments, account log in, etc.

About Keycard: Secure, Contactless, Open Source Hardwallet
Keycard is an open framework for smartcards in the crypto space. Smartcards are cost-effective, highly secure hardware, that can generate & store private keys, sign transactions with a tap on a mobile (android & ios sdk available), or with a desktop (with a usb reader).

Keycard can be used as an easy-to-use and mobile friendly hardware wallet, bringing security and ownership over their keys to end users. Its form factor, tangibility and cost effectiveness can also be leveraged as an adoption tool, to bring new comers to decentralized services.

Keycard has an Android, iOS SDK & Go SDK.
Keycard is integrated with geth.

Developer Guide: Full documentation and links to repos can be found here: https://keycard.tech/docs/

How to get a Keycard: If you want to hack with Keycard, get in touch with us, let us know what you plan to build, and we will send you a keycard!:

Submission Requirements

  • Eligible projects must utilize the Keycard Hardware and the API for integration.
  • Must present a working demo
  • Must be open source

Submission Deadline

Due July 6, 2020

Judging Criteria

The prize will be awarded to the individual/team that produces the most creative integration with Keycard and the best user experience while respecting the challenge description.

Winner Announcement Date

July 9, 2020

Implement EIP-1581

Current proposal is at https://notes.status.im/s/SJMhfgMhm and needs to be transformed into an EIP. Implementation means allowing export of the private keys under this subtree (PIN required) and implement some ad-hoc caching to speed performance up.

[API Question] How to get the transaction hash before signing?

Hello everyone,

I have followed the documentation and examples for the keycard integration, and I am very close to have a functional app but I got stuck on the following step:

You should instead calculate the transaction hash, according to the rules of the cryptocurrency you are handling and send that for signature instead.

Is there any example where I can see how to get the transaction hash before signing?

I am currently using Web3j but I am open to any other way of doing that.

Thanks a lot and keep the great work!

Plausible deniability

as talked about the magicians gathering after cryptolife: It would be great to be able to specify N>=1 PINs to lead to different derivation paths to gain plausible deniability.

Implement on-card key generation & backup

Most wallets are using BIP39 with the mnemonic seed for backup/restore. This means that the key always leaves the device (having the user write it down on paper also counts as leaving the device) even for hardware wallets.

We must certainly support BIP39 (we do!), but we also need to allow generating keys on-card, with the ability to back them up to other cards.

After some discussion and thought, I have the following proposal which allows the user and/or wallet developer to choose the level of security desired and does not require trust of the issuer.

  1. A backup session is started by the owner, who taps and authenticates with PIN to all cards partecipating (1 source and n targets) and specifies how many client devices will be used to generate entropy for the encryption key. It can be 1 (must be highly discouraged in UI) to X. The card will then accept exactly X pieces of entropy to be loaded. The device starting the backup also puts the first piece of entropy.

  2. The owner taps the involved cards on the specified number of devices without any pairing or PIN authentication. Each device must generate one random 256-bit number and shot it to all cards using a one-shot secure channel (similar to what we do for the INIT APDU). The card adds this number to its internal state. Using XOR to combine the state makes the order in which the taps happen irrelevant.

  3. At the end of this procedure, all cards have the same piece of random information, but none of the client has more than 1 piece of the puzzle (unless a single client is being used).

  4. The user than takes the source card and taps it to actually make a backup. This will require PIN entry authentication and will use the key generated following the procedure above. It will return the plain key uid, a random IV and the encrypted private master key and chain code. The backup key is then destroyed so further backups will require repeating the procedure.

  5. The user will then tap and authenticate to all target cards which will receive the backup generated previously. The cards will decrypt the backup using the key generated previously and verify that the key UID matches. If it matches the key becomes the new master key of the card, which means the backup is succeful. Also in this case, the backup key is destroyed.

Access to the hardwallet smartcard from a web browser

It would make a lot of sense to allow web apps to communicate with our smartcard on a desktop.

Trusted web apps could use the card to sign transactions, or use the card as a second factor authentification (proof-of-having the card, proof-of-knowledge through PIN entry)

Our cards is accessible through a PC/SC interface. This is the main hurdle to overcome to here.

Ideally (from a user perspective) we’d like to do that without any extension to the browser, or driver installed. It seems that this is not possible through existing browsers and javascript only. See some discussions here

As a back-up we can think of other possible solutions

  • With browser extensions:
    • Which only goal would be to add PC/SC access to the browser. See example here
    • If commonly used web3 extensions like Metamask would integrate a PC/SC driver to allow usage of smartcard hardwallets
  • With a walletconnect type of scenario, where we have an application (either a status like application, or a dedicated walletconnect to smartcard bridge application)

Mention card keys used to lock card during install in the README.md

When installing the cap file, the gradle install task changes the javacard keys from the default development keys to: c212e073ff8b4bbfaff4de8ab655221f

IMHO this should be mentioned in the README, so users can unlock their cards without searching for this key in the source.

Proof of concept for integration of Keycard within mobile or desktop apps

Title: Proof of concept for integration of Keycard within mobile or desktop apps

About Keycard: Keycard is an open framework for smartcards in the crypto sphere. Smartcards are cost-effective, highly secure hardware, that can generate & store private keys, sign transactions with a tap on a mobile (android sdk available), or with a desktop (with a usb reader).

Keycard can be used as an easy-to-use and mobile friendly hardware wallet, bringing security and ownership over their keys to end users. Its form factor, tangibility and cost effectiveness can also be leveraged as an adoption tool, to bring new comers to decentralized services.

  • Keycard has an Android SDK & Go SDK.
  • Keycard is integrated with geth.

Challenge description: We’d love to see a proof of concept of integration of Keycard within mobile or desktop apps (e.g. wallets, web3 browsers) for security, dapps interaction, or payment purposes.

Developer Guide:
Full documentation and links to repos can be found here:
https://status.im/keycard_api/

How to get a Keycard:
If you want to hack with Keycard, get in touch with us on https://get.status.im/chat/public/status-keycard, let us know what you plan to build, and we will send you a keycard!

Prize: 2,000 DAI

Recommended javacard?

Hi folks,

I've been looking through JCAlgTest for a suitable card, but I've yet to find anything suitable (Infineon SLE78 Universal JCard appears the closest but doesn't support JC 3.0.4). Do you guys have any recommendations?

Cheers,

Rowland

Drop block signing support

We currently support ECDSA-SHA256 signature of data sent in blocks (instead of precomputed hash). This function is never used and is a remaint from the very first proof of concept. I also see no real advantage in doing that, since generating the hash off-card is trivial.

Pairing multiple devices?

I noticed your Keycard applet has a configurable number of pairing slots, which is hardcoded to 5 here. This would imply you want to allow multiple pairings for a given card.

Aside: We at GridPlus actually discovered issues with this (namely, a user who tries to pair with a new device when the card is at its limit would be unable to use the card since only a paired device can unpair). We have implemented an alternative that simply overwrites the first pairing slot whenever a pairing is made - this is better for our use case.

However, it seems like a user can only pair if a pairingSecret is loaded (used here) and the only way to load it is via the INIT command (here you can see the command getting blocked if pairingSecret has already been set).

Is this intentional? It seems odd to have the following both be true:

  • 5 pairing slots
  • Only the client that initializes the card can ever pair with it

Is there another way to allow pairing with multiple devices?

Aside: We are working on a "re-init" function (PR here), which allows a new device to load its own pairingSecret after the card has been initialized. Of course this means that the old pairing will be invalid, but this is not a problem for us (see earlier Aside).

[2,000 DAI] - Integrate Keycard with a dApp

Integrate Keycard with a dApp

"Important To participate in this bounty you'll need a physical Keycard mailed to you. Please express interest in the bounty with your project idea detailed in the work plan, and we will reach out to get your information and send you a Keycard ASAP!"

Prize Bounty

2,000 DAI

Challenge Description

Develop a dApp that uses the Keycard Cash applet with the Web3 javascript API https://keycard.tech/docs/web3.html to enable any type of use cases with smart contracts (e.g but not restricted to payments or redeeming assets for smart contracts)

About Keycard: Secure, Contactless, Open Source Hardwallet
Keycard is an open framework for smartcards in the crypto sphere. Smartcards are cost-effective, highly secure hardware, that can generate & store private keys, sign transactions with a tap on a mobile (android & ios sdk available), or with a desktop (with a usb reader).

Keycard can be used as a easy-to-use and mobile friendly hardware wallet, bringing security and ownership over their keys to end users. Its form factor, tangibility and cost effectiveness can also be leveraged as an adoption tool, to bring new comers to decentralized services.

Keycard can be easily integrated with dApps browsed on Status browser. Keycard embeds a second applet (Keycard Cash) with a lower security profile than the main applet (used for high security hardware wallet scenarios). Any dApps can use web3 javascript API that will prompt Status browser to sign a meta-transaction provided by the dApp. The signature of the meta-transaction is performed by the keycard tapped. This keycard doesn't need to be paired with the phone. This allows a range of applications like payments with smart contract wallets, redeeming assets from contracts. See documentation here https://keycard.tech/docs/web3.html

Keycard has an Android, iOs SDK & a Go SDK.
Keycard is integrated with geth.

Developer Guide: Full documentation and links to repos can be found here: https://keycard.tech/docs/

How to get a Keycard: If you want to hack with Keycard, get in touch with us, let us know what you plan to build, and we will send you a keycard!:

Submission Requirements

  • Eligible projects must utilize the Keycard Hardware and the javascript web3 API to integrate it with a dApp
  • Must present a working demo
  • Must be open source

Submission Deadline

Due July 6, 2020

Judging Criteria

  • Most creative DApp created with Keycard

Winner Announcement Date

July 9, 2020

Initialization is not as expected

I got some Keycard with applet v2.1. I can initialize and use them with WallETH.

Then, I tried to handle them on my own, because for now, there's only Java available. I'm facing a weird behavior with uninitialized keycards :
After the SELECT (providing a session card PubKey only), what ever the command sent, the cards answers 0x9000 and no data.
It should answer SW_INS_NOT_SUPPORTED = 0x6D00 to any command which is different from 0x80FE. In the case the card is in "secure channel" mode it ca respond with 9000 on every request but it has to be some data in the answer.
as in, the card shall answer directly 6D00 for any different command :
https://github.com/status-im/status-keycard/blob/master/src/main/java/im/status/keycard/KeycardApplet.java#L324
Maybe, there's an issue in the if else... statements. Does anyone is reproducing the same?

Compilation error: package javax.smartcardio is not visible

Hello,
I followed the compilations instructions.
When running ./gradlew convertJavacard (JDK 10.0.2) I get the following error:

/java-applet/buildSrc/src/main/java/im/status/keycard/build/InstallTask.java:12: error: package javax.smartcardio is not visible
import javax.smartcardio.*;
^
(package javax.smartcardio is declared in module java.smartcardio, which is not in the module graph)
/java-applet/buildSrc/src/main/java/im/status/keycard/build/InstallTask.java:49: error: cannot access CardChannel
PCSCCardChannel sdkChannel = new PCSCCardChannel(apduCard.getBasicChannel());
^
class file for javax.smartcardio.CardChannel not found
2 errors

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':buildSrc:compileJava'.

Compilation failed; see the compiler error output for details.

Any idea?

One signature per power-up

It could be beneficial to give the option to the user to only allow 1 transaction to be signed per tap (where a tap represents a power-cycle). This would make it easier to detect a compromised client since it would prevent it to sign additional, unrequested transactions when signing yours (it can do it but then on etherescan you wouldn't find your transaction, since it only signed the unrequested one).

The implications on usability have to be evaluated and it should only be implemented as an option, since some use case might require several transactions to be signed at once.

PUK retry counter not honoured

The latest 2.2.1 release of the keycard app permits an unlimited number of PUK retries. At least definitely not 5 as it's speced in the source code, as I've tried at least 25 wrong ones and then the good PUK still lets me in.

Signatures sometimes contain 33-byte components

In running the tests, I have noticed that sometimes I get signatures with 33-byte X-components (as opposed to 32-byte ones, which I would expect every time).

Here's an example:

My comments in verifySignResp in KeycardTest.java:

private void verifySignResp(byte[] data, APDUResponse response) throws Exception {
Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
assertEquals(0x9000, response.getSw());
byte[] sig = response.getData();
System.out.println("verify data");
System.out.println(Arrays.toString(sig));
byte[] keyData = extractPublicKeyFromSignature(sig);
sig = extractSignature(sig);
System.out.println("verify sig");
System.out.println(Arrays.toString(sig));

ECParameterSpec ecSpec = ECNamedCurveTable.getParameterSpec("secp256k1");
ECPublicKeySpec cardKeySpec = new ECPublicKeySpec(ecSpec.getCurve().decodePoint(keyData), ecSpec);
ECPublicKey cardKey = (ECPublicKey) KeyFactory.getInstance("ECDSA", "BC").generatePublic(cardKeySpec);

signature.initVerify(cardKey);
assertEquals((SecureChannel.SC_KEY_LENGTH * 2 / 8) + 1, keyData.length);
signature.update(data);
assertTrue(signature.verify(sig));
assertFalse(isMalleable(sig));
}

Produces the following output:

verify data
[-96, -127, -118, -128, 65, 4, 75, -98, 34, 38, 36, -11, 92, 24, -115, 22, -69, -57, 30, -76, -91, 124, -41, -18, -14, -33, 91, -33, 78, 63, 45, -27, -78, -92, 94, 92, 68, -90, -110, -46, -70, 101, -109, 60, 94, -1, 118, 38, -55, 95, -95, -50, 90, 110, 116, 79, -19, 16, -69, 31, -47, -124, 103, -18, 105, 49, -86, 14, -58, -4, 48, 69, 2, 33, 0, -25, 6, -126, -104, -39, 81, 106, -79, -119, -27, 61, 15, -1, 114, -25, 106, -107, -11, -52, -53, 73, 19, 28, 43, 108, -18, 55, 18, 125, 87, 11, 92, 2, 32, 83, 90, -26, -14, -50, 18, -46, -82, 103, 46, -10, 71, -76, 71, -19, 53, 23, -122, -109, -90, -21, -99, 76, 4, 3, -55, 35, 56, -114, -64, 40, 7]
verify sig
[48, 69, 2, 33, 0, -25, 6, -126, -104, -39, 81, 106, -79, -119, -27, 61, 15, -1, 114, -25, 106, -107, -11, -52, -53, 73, 19, 28, 43, 108, -18, 55, 18, 125, 87, 11, 92, 2, 32, 83, 90, -26, -14, -50, 18, -46, -82, 103, 46, -10, 71, -76, 71, -19, 53, 23, -122, -109, -90, -21, -99, 76, 4, 3, -55, 35, 56, -114, -64, 40, 7]

A different output, with the 32-byte component I would expect:

verify data
[-96, -127, -119, -128, 65, 4, 75, -98, 34, 38, 36, -11, 92, 24, -115, 22, -69, -57, 30, -76, -91, 124, -41, -18, -14, -33, 91, -33, 78, 63, 45, -27, -78, -92, 94, 92, 68, -90, -110, -46, -70, 101, -109, 60, 94, -1, 118, 38, -55, 95, -95, -50, 90, 110, 116, 79, -19, 16, -69, 31, -47, -124, 103, -18, 105, 49, -86, 14, -58, -4, 48, 68, 2, 32, 63, 86, -119, 57, 51, -126, 106, 113, 88, 112, -113, -41, -113, -11, 117, -63, -123, -6, -48, -77, -14, 17, 44, -114, 7, 83, -34, 119, 91, 67, 27, 81, 2, 32, 97, -58, -120, 110, 105, 125, -48, -48, 3, -78, -112, 73, 2, -3, -110, -5, 63, 48, -116, -95, 36, -31, -30, 7, -8, 82, -29, -23, 90, 57, 72, -12]
verify sig
[48, 68, 2, 32, 63, 86, -119, 57, 51, -126, 106, 113, 88, 112, -113, -41, -113, -11, 117, -63, -123, -6, -48, -77, -14, 17, 44, -114, 7, 83, -34, 119, 91, 67, 27, 81, 2, 32, 97, -58, -120, 110, 105, 125, -48, -48, 3, -78, -112, 73, 2, -3, -110, -5, 63, 48, -116, -95, 36, -31, -30, 7, -8, 82, -29, -23, 90, 57, 72, -12]

Note:

  • Only the X component ever appears to be affected (I have yet to see a 70-byte signature output, which would indicate both components are 33 bytes)
  • The frequency looks roughly like ~1 in 7 attempts

Have you observed this behavior? Do you know the root cause? How do you avoid buffer overflows in parsing the output? My strategy given current knowledge would be to simply remove the leading zero if the component is >32 bytes - do you have a better strategy?

Trusted JCOP implementation

Any javacard smartcard is based on closed source JCOP implementation.
How JCOP is deployed to smartcard eeprom and could it be theoretically replaced with one compiled from sources?

Make upgradable

It became pretty clear, that the applet will need to be upgradable. At the moment this will be obtained by simply leaving the card with default Global Platform keys. However in the future we could use a key derived from the master wallet for upgrades (this means requiring a PIN to accept upgrading).

Upgrading removes the stored keys, PIN(s) etc. This means the procedure will not be as straightforward and will require backups. We must make sure upgrades are released only when strictly needed for introducing additional features. This also means that when we do a release we must be fairly sure that there are no bugs, especially security-related ones. This is currently achieved through extensive testing of all possible error conditions and malformed inputs.

Preloaded cryptocards in retail

One of the main characteristic of smartcard-based hardwallets is their low cost. This kind of cards can be a very good support to trigger adoption of crypto-currencies for those who don’t want to go through an exchange to buy crypto.

Some paper-wallets type of cards like ether.cards https://ether.cards/ offer this type of convenience by providing an already generated wallet, and will probably soon offer the same type of cards with a pre-paid amount of crypto on the wallet. We think that using a smartcard instead of a paper wallet for this type of scenarios could provide several security and convenience advantages.

In our current simple deployment scheme, the cards are delivered to the user without any wallet key pair. There is neither any specific mechanism already defined to uniquely identify each card.

There are two use cases that would make sense :

1/ prepaid card
Our card is advertised as holding 50$ (example) of eth. The user buys this card in with 50$ of fiat in a store or online. When the user receives this card, he is guided (ideally through a secure tap-to-download an app feature) through an application (e.g. Status app) to activate his card, and his wallet is automatically filled with 50$ worth of crypto at the current exchange rate.

2/ empty card
Same scenario but sold in store. The user picks up a blank card, goes to the cashier, asks for the Fiat amount he wants to put on the card and the crypto type (« let me get 35$ of eth, please 🙂 « ). The cashier has a dedicated app on his phone, or a dedicated POS, cashes in the 35$ and provision the crypto in the card.

Let’s brainstorm on what are the difficulties, and come up with a full system solution.

Auto Pair Issue

Hello,
Trying to use the code with my status keycard(It is black,).
I am able to fetch the info from it
08-20 15:21:41.542 9643-9663/im.status.keycard.demo I/MainActivity: Instance UID: 8c82bedc0b65b9d75d5a9b6b29ee52d8
08-20 15:21:41.542 9643-9663/im.status.keycard.demo I/MainActivity: Secure channel public key: 04187e3f406db8852fae444b635949e09140a556af6ef8ed0a7163ce0f01ad5d85be96f746a1cd2a2a21c90907eebd4cf99649b09969fc0514fefbd09a5143978c
08-20 15:21:41.542 9643-9663/im.status.keycard.demo I/MainActivity: Application version: 2.1
08-20 15:21:41.542 9643-9663/im.status.keycard.demo I/MainActivity: Free pairing slots: 0
08-20 15:21:41.542 9643-9663/im.status.keycard.demo I/MainActivity: Key UID: 654cd70200be6f694a1ff76dce94b446cfb48543bae855419519ed9cb4459aa6
08-20 15:21:41.542 9643-9663/im.status.keycard.demo I/MainActivity: Capabilities: 0F
08-20 15:21:41.543 9643-9663/im.status.keycard.demo I/MainActivity: Has Secure Channel: true
08-20 15:21:41.543 9643-9663/im.status.keycard.demo I/MainActivity: Has Key Management: true
08-20 15:21:41.543 9643-9663/im.status.keycard.demo I/MainActivity: Has Credentials Management: true
08-20 15:21:41.543 9643-9663/im.status.keycard.demo I/MainActivity: Has NDEF capability: true
08-20 15:21:41.543 9643-9663/im.status.keycard.demo I/MainActivity: Has cmdh: 0
08-20 15:21:41.543 9643-9663/im.status.keycard.demo D/CardChannel: COMMAND CLA: 80 INS: 20 P1: 00 P2: 00 LC: 06
08-20 15:21:41.629 9643-9663/im.status.keycard.demo D/CardChannel: RESPONSE LEN: 00, SW: 6985
But when I am trying to call cmdSet.verifyPin("000000");

I am getting below error:

08-20 15:21:41.630 9643-9663/im.status.keycard.demo W/System.err: im.status.keycard.io.APDUException: SW_CONDITIONS_OF_USE_NOT_SATISFIED, 0x6985
08-20 15:21:41.630 9643-9663/im.status.keycard.demo W/System.err: at im.status.keycard.io.APDUResponse.checkSW(APDUResponse.java:91)
08-20 15:21:41.630 9643-9663/im.status.keycard.demo W/System.err: at im.status.keycard.io.APDUResponse.checkOK(APDUResponse.java:64)
08-20 15:21:41.630 9643-9663/im.status.keycard.demo W/System.err: at im.status.keycard.io.APDUResponse.checkAuthOK(APDUResponse.java:109)
08-20 15:21:41.630 9643-9663/im.status.keycard.demo W/System.err: at im.status.keycard.app.MainActivity$1.onConnected(MainActivity.java:74)
08-20 15:21:41.630 9643-9663/im.status.keycard.demo W/System.err: at im.status.keycard.android.NFCCardManager.onCardConnected(NFCCardManager.java:97)
08-20 15:21:41.630 9643-9663/im.status.keycard.demo W/System.err: at im.status.keycard.android.NFCCardManager.run(NFCCardManager.java:80)
08-20 15:21:41.630 9643-9663/im.status.keycard.demo E/MainActivity: SW_CONDITIONS_OF_USE_NOT_SATISFIED, 0x6985

Also when I am calling cmdSet.autoPair("KeycardTest");
It gives me IO Exception.
Any thing which I am missing. Or I need to format the card and then intialize everything again

UnblockPIN and VerifyPIN have differing behaviors

Hey, played around with it a bit more and can confirm that the PUK is properly decremented if I supply all the needed 12 + 6 bytes.

However, then I have a different issue:

  • In unblockPIN, you verify that the PUK + PIN is 18 digits, and don't fail the PUK attempt if the input is bad. This is imho good behavior.
  • In verifyPIN however you do not check that the length is 6 digitas, so you do fail the PIN attempt if the input is bad.

I think both behaviors is fine as long as they are consistent across each other. At least this is what I would expect.

Remove GPShell dependency

GPShell is becoming more and more difficult to install on modern computers. We can rewrite applet installation using our own SDK.

Rename to keycard

Replace every reference to hardwallet or hardwallet lite with Keycard. This also applies to the SDK.

Secure tap-to-download app feature

We have much brainstormed if we should load an applet in the card that allows the user

  • tap-to-download: first time he takes the card in his hands and tap with the mobile, the mobile prompts the Playstore page for Status app
  • tap-to-launch: later on, when app is is installed, tapping the card on the mobile launches Status app.

We have decided to not allow tap-to-download for security reasons. This is a convenience vs security compromise.

However, we will enable tap-to-launch app in our applet.

The reasoning was the following (this is an extract of our discussion at cryptolife):

" In our current deployment scheme, the trust in the system constituted by the mobile app + the smartcard, relies on the trust that the user uses the authentic mobile app (here Status client).

Why can’t in any case the real app be fooled by a malveillant card? The real app will ask to pair with the card and ask for the pairing code. If the card is a malveillant one, then a pairing code must have been given to the user through a paper or printed on the card. The real app shows to the user a warning message when asking for pairing that this pairing was written down by the user itself, given by status app, and no other form is acceptable.

The convenience of tap-to-download is real, but:
*The security threat is real and inexpensive: it’s very easy to forge a false card that would tap to download a wrong app
*If we we put tap to download in our card, then it will be more complex to explain the security risk.
* No tap to download : « You need to manually find status.im on the app store, never follow some links, QR codes, or NFC tag including on a card that looks like Status card"
* Tap to download : « When your card prompts you to a playstore app, make sure this is the real status app that is prompted to you"
*If Status app is removed from the playstore in some regions, then the tap to download will not work, which is bad user experience.
"

Also, if we follow this logic, we should not put any QR code in the packaging.

Since having a tap-to-download feature would still be very relevant from a convenience stand point, we need to find other deployment scenarios and security scheme, where tap-to-download does not increase the security risk.

Add multiple and/or rule-based PIN-less path

At the moment, only one derivation path can be set as PIN-less. Most likely we will want several paths or even subtrees to be PIN-less for some non-wallet usages.

We should define the mechanism to allow this

Docs dead link

Documentation link https://keycard.status.im/api/ in README is dead. Please update.
Thanks

[1,000 DAI] - Create a New SDK or Development Tool Facilitating Integration of Keycard

Create a New SDK or Development Tool Facilitating Integration of Keycard

"Important To participate in this bounty you'll need a physical Keycard mailed to you. Please express interest in the bounty with your project idea detailed in the work plan, and we will reach out to get your information and send you a Keycard ASAP!"

Prize Bounty

1,000 DAI

Challenge Description

Keycard currently have a android SDK, a iOS SDK and a Go SDK, it's also integrated in Geth. We'd love to see hackers create new SDKs, or new development tools that are facilitating integration of Keycard in various environments.

About Keycard: Secure, Contactless, Open Source Hardwallet
Keycard is an open framework for smartcards in the crypto space. Smartcards are cost-effective, highly secure hardware, that can generate & store private keys, sign transactions with a tap on a mobile (android & ios sdk available), or with a desktop (with a usb reader).

Keycard can be used as an easy-to-use and mobile friendly hardware wallet, bringing security and ownership over their keys to end users. Its form factor, tangibility and cost effectiveness can also be leveraged as an adoption tool, to bring new comers to decentralized services.

Keycard has an Android, iOS SDK & Go SDK.
Keycard is integrated with geth.

Developer Guide: Full documentation and links to repos can be found here: https://keycard.tech/docs/

How to get a Keycard: If you want to hack with Keycard, get in touch with us, let us know what you plan to build, and we will send you a keycard!:

Submission Requirements

  • Eligible projects must utilize the Keycard Hardware and the API for integration.
  • Must present a working demo
  • Must be open source

Submission Deadline

Due July 6, 2020

Judging Criteria

The prize will be awarded to the individual/team that produces the most usefull tool to facilitate further integration of Keycard in various environments

Winner Announcement Date

July 9, 2020

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.