Skip to content

Commit

Permalink
Merge pull request #293 from Concordium/hd-wallet
Browse files Browse the repository at this point in the history
Key derivation
  • Loading branch information
orhoj authored Jan 17, 2024
2 parents a4399a6 + f35407d commit c44c716
Show file tree
Hide file tree
Showing 13 changed files with 3,351 additions and 3 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Changelog

## Unreleased changes
- Purge remaining usages of V1 GRPC API.

- Purge remaining usages of V1 GRPC API.
- Added support for android through an AAR artifact.
- Added `ConcordiumHdWallet` class for deriving Concordium specific keys and randomness from a seed phrase.

## 6.0.0
- Added method `waitUntilFinalized` for waiting until a given transaction is finalized.
Expand Down
5 changes: 5 additions & 0 deletions concordium-android-sdk/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@
<artifactId>jackson-datatype-jdk8</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>org.bitcoinj</groupId>
<artifactId>bitcoinj-core</artifactId>
<version>0.16.2</version>
</dependency>
</dependencies>

<profiles>
Expand Down
5 changes: 5 additions & 0 deletions concordium-sdk/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
</properties>

<dependencies>
<dependency>
<groupId>org.bitcoinj</groupId>
<artifactId>bitcoinj-core</artifactId>
<version>0.16.2</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package com.concordium.sdk.crypto;

import com.concordium.sdk.crypto.wallet.Network;
import com.concordium.sdk.crypto.wallet.StringResult;
import com.concordium.sdk.exceptions.JNIError;
import com.concordium.sdk.transactions.InitName;
import com.concordium.sdk.transactions.ReceiveName;
import com.concordium.sdk.transactions.smartcontracts.SchemaParameter;
import com.concordium.sdk.transactions.smartcontracts.SchemaVersion;
import com.concordium.sdk.transactions.smartcontracts.SerializeParameterResult;
import com.concordium.sdk.types.ContractAddress;

import lombok.SneakyThrows;

public class CryptoJniNative {
Expand Down Expand Up @@ -110,4 +114,148 @@ public static String serializeInitParameter(SchemaParameter parameter, InitName
}
private static native String serializeInitParameter(String parameterJson, String contractName, byte[] schemaBytes, int schemaVersion, boolean verboseErrors);

/**
* Derives an account signing key from the provided seed and network for the given indices.
* @param seedAsHex the seed derived from a seed phrase as a hex string
* @param network the network that the derived key is for
* @param identityProviderIndex the index of the identity provider that the account is associated with interpreted as a u32.
* @param identityIndex the index of the identity that the account is associated with interpreted as a u32.
* @param credentialCounter the number of the credential interpreted as a u32.
* @return JSON representing {@link StringResult}. If successful the field 'result' contains the hex encoded account signing key.
* If not successful, the 'err' field contains a {@link JNIError} detailing what went wrong.
*/
public static String getAccountSigningKey(String seedAsHex, Network network, int identityProviderIndex, int identityIndex, int credentialCounter) {
return getAccountSigningKey(seedAsHex, network.getValue(), identityProviderIndex, identityIndex, credentialCounter);
}
private static native String getAccountSigningKey(String seedAsHex, String network, int identityProviderIndex, int identityIndex, int credentialCounter);

/**
* Derives an account public key from the provided seed and network for the given indices.
* @param seedAsHex the seed derived from a seed phrase as a hex string
* @param network the network that the derived key is for
* @param identityProviderIndex the index of the identity provider that the account is associated with interpreted as a u32.
* @param identityIndex the index of the identity that the account is associated with interpreted as a u32.
* @param credentialCounter the number of the credential interpreted as a u32.
* @return JSON representing {@link StringResult}. If successful the field 'result' contains the hex encoded account public key.
* If not successful, the 'err' field contains a {@link JNIError} detailing what went wrong.
*/
public static String getAccountPublicKey(String seedAsHex, Network network, int identityProviderIndex, int identityIndex, int credentialCounter) {
return getAccountPublicKey(seedAsHex, network.getValue(), identityProviderIndex, identityIndex, credentialCounter);
}
private static native String getAccountPublicKey(String seedAsHex, String netAsStr, int identityProviderIndex, int identityIndex, int credentialCounter);

/**
* Derives id cred sec from the provided seed and network for the given indices.
* @param seedAsHex the seed derived from a seed phrase as a hex string
* @param network the network that the derived key is for
* @param identityProviderIndex the index of the identity provider that the account is associated with interpreted as a u32.
* @param identityIndex the index of the identity that the account is associated with interpreted as a u32.
* @return JSON representing {@link StringResult}. If successful the field 'result' contains the hex id cred sec.
* If not successful, the 'err' field contains a {@link JNIError} detailing what went wrong.
*/
public static String getIdCredSec(String seedAsHex, Network network, int identityProviderIndex, int identityIndex) {
return getIdCredSec(seedAsHex, network.getValue(), identityProviderIndex, identityIndex);
}
private static native String getIdCredSec(String seedAsHex, String netAsStr, int identityProviderIndex, int identityIndex);

/**
* Derives a PRF-key from the provided seed and network for the given indices.
* @param seedAsHex the seed derived from a seed phrase as a hex string
* @param network the network that the derived key is for
* @param identityProviderIndex the index of the identity provider that the account is associated with interpreted as a u32.
* @param identityIndex the index of the identity that the account is associated with interpreted as a u32.
* @return JSON representing {@link StringResult}. If successful the field 'result' contains the hex encoded PRF-key.
* If not successful, the 'err' field contains a {@link JNIError} detailing what went wrong.
*/
public static String getPrfKey(String seedAsHex, Network network, int identityProviderIndex, int identityIndex) {
return getPrfKey(seedAsHex, network.getValue(), identityProviderIndex, identityIndex);
}
private static native String getPrfKey(String seedAsHex, String netAsStr, int identityProviderIndex, int identityIndex);

/**
* Gets the credential ID for a specific credential defined by the identity provider index,
* identity index and the credential counter.
* @param seedAsHex the seed derived from a seed phrase as a hex string
* @param network the network that the derived key is for
* @param identityProviderIndex the index of the identity provider that the account is associated with interpreted as a u32.
* @param identityIndex the index of the identity that the account is associated with interpreted as a u32.
* @param credentialCounter the credential number of the credential to get the id for interpreted as a u8.
* @param commitmentKey the on chain commitment key. This value can be retrieved from a node through its gRPC interface.
* @return JSON representing {@link StringResult}. If successful the field 'result' contains the hex encoded credential id.
* If not successful, the 'err' field contains a {@link JNIError} detailing what went wrong.
*/
public static String getCredentialId(String seedAsHex, Network network, int identityProviderIndex, int identityIndex, int credentialCounter, String commitmentKey) {
return getCredentialId(seedAsHex, network.getValue(), identityProviderIndex, identityIndex, credentialCounter, commitmentKey);
}
private static native String getCredentialId(String seedAsHex, String netAsStr, int identityProviderIndex, int identityIndex, int credentialCounter, String commitmentKey);

/**
* Derives the signature blinding randomness for a specific identity.
* @param seedAsHex the seed derived from a seed phrase as a hex string
* @param network the network that the derived randomness is for
* @param identityProviderIndex the index of the identity provider interpreted as a u32.
* @param identityIndex the index of the identity interpreted as a u32.
* @return JSON representing {@link StringResult}. If successful the field 'result' contains the hex encoded signature blinding randomness.
* If not successful, the 'err' field contains a {@link JNIError} detailing what went wrong.
*/
public static String getSignatureBlindingRandomness(String seedAsHex, Network network, int identityProviderIndex, int identityIndex) {
return getSignatureBlindingRandomness(seedAsHex, network.getValue(), identityProviderIndex, identityIndex);
}
private static native String getSignatureBlindingRandomness(String seedAsHex, String netAsStr, int identityProviderIndex, int identityIndex);

/**
* Derives the attribute commitment randomness for a specific attribute.
* @param seedAsHex the seed derived from a seed phrase as a hex string
* @param network the network that the derived randomness is for
* @param identityProviderIndex the index of the identity provider interpreted as a u32.
* @param identityIndex the index of the identity interpreted as a u32.
* @param credentialCounter the credential number that the attribute is randomness is for interpreted as a u32.
* @param attribute the attribute key index interpreted as a u8.
* @return JSON representing {@link StringResult}. If successful the field 'result' contains the hex encoded attribute commitment randomness.
* If not successful, the 'err' field contains a {@link JNIError} detailing what went wrong.
*/
public static String getAttributeCommitmentRandomness(String seedAsHex, Network network, int identityProviderIndex, int identityIndex, int credentialCounter, int attribute) {
return getAttributeCommitmentRandomness(seedAsHex, network.getValue(), identityProviderIndex, identityIndex, credentialCounter, attribute);
}
private static native String getAttributeCommitmentRandomness(String seedAsHex, String netAsStr, int identityProviderIndex, int identityIndex, int credentialCounter, int attribute);

/**
* Derives a verifiable credential signing key.
* @param seedAsHex the seed derived from a seed phrase as a hex string
* @param network the network that the derived randomness is for
* @param issuer the verifiable credential issuer contract
* @param verifiableCredentialIndex the index of the verifiable credential to derive a signing key for interpreted as a u32
* @return JSON representing {@link StringResult}. If successful the field 'result' contains the hex encoded verifiable credential signing key.
* If not successful, the 'err' field contains a {@link JNIError} detailing what went wrong.
*/
public static String getVerifiableCredentialSigningKey(String seedAsHex, Network network, ContractAddress issuer, int verifiableCredentialIndex) {
return getVerifiableCredentialSigningKey(seedAsHex, network.getValue(), issuer.getIndex(), issuer.getSubIndex(), verifiableCredentialIndex);
}
private static native String getVerifiableCredentialSigningKey(String seedAsHex, String netAsStr, long issuerIndex, long issuerSubindex, int verifiableCredentialIndex);

/**
* Derives a verifiable credential public key.
* @param seedAsHex the seed derived from a seed phrase as a hex string
* @param network the network that the derived randomness is for
* @param issuer the verifiable credential issuer contract
* @param verifiableCredentialIndex the index of the verifiable credential to derive a public key for interpreted as a u32
* @return JSON representing {@link StringResult}. If successful the field 'result' contains the hex encoded verifiable credential public key.
* If not successful, the 'err' field contains a {@link JNIError} detailing what went wrong.
*/
public static String getVerifiableCredentialPublicKey(String seedAsHex, Network network, ContractAddress issuer, int verifiableCredentialIndex) {
return getVerifiableCredentialPublicKey(seedAsHex, network.getValue(), issuer.getIndex(), issuer.getSubIndex(), verifiableCredentialIndex);
}
private static native String getVerifiableCredentialPublicKey(String seedAsHex, String netAsStr, long issuerIndex, long issuerSubindex, int verifiableCredentialIndex);

/**
* Derives the verifiable credential backup encryption key. This key should be used to encrypt
* the backup file of verifiable credentials. The key is derived from the seed phrase so that
* a user can access the backup file when only holding the seed phrase.
* @return JSON representing {@link StringResult}. If successful the field 'result' contains the hex encoded verifiable credential backup encryption key.
* If not successful, the 'err' field contains a {@link JNIError} detailing what went wrong.
*/
public static String getVerifiableCredentialBackupEncryptionKey(String seedAsHex, Network network) {
return getVerifiableCredentialBackupEncryptionKey(seedAsHex, network.getValue());
}
private static native String getVerifiableCredentialBackupEncryptionKey(String seedAsHex, String netAsStr);
}
Loading

0 comments on commit c44c716

Please sign in to comment.