Skip to content

Commit

Permalink
Merge pull request #34 from lacchain/p256-support
Browse files Browse the repository at this point in the history
P256 support
  • Loading branch information
eum602 authored Oct 10, 2023
2 parents 6e055db + e9512da commit 6b33c68
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 32 deletions.
1 change: 1 addition & 0 deletions .example.env
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ SECP256K1_KEY=/secp256k1
SECP256K1_SIGN_ETHEREUM_TRANSACTION=/secp256k1/sign/ethereum-tx
SECP256K1_SIGN_LACCHAIN_TRANSACTION=/secp256k1/sign/lacchain-tx
ED25519_CREATE_KEY=/ed25519
P256_CREATE_KEY=/p256

# Did Registry
CHAIN_ID = 0x9e55c
Expand Down
1 change: 1 addition & 0 deletions .example.env.dev
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ SECP256K1_KEY=/secp256k1
SECP256K1_SIGN_ETHEREUM_TRANSACTION=/secp256k1/sign/ethereum-tx
SECP256K1_SIGN_LACCHAIN_TRANSACTION=/secp256k1/sign/lacchain-tx
ED25519_CREATE_KEY=/ed25519
P256_CREATE_KEY=/p256


# Did Registry
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 0.0.3

* Add support to associate a P-256 JWK to a DID
## 0.0.1

### Additions and Improvements
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lacchain-identity",
"version": "0.0.2",
"version": "0.0.6",
"description": "Rest api for lacchain identity manager",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
Expand Down Expand Up @@ -85,7 +85,7 @@
"helmet": "^5.0.2",
"json-canonicalize": "^1.0.6",
"jsonwebtoken": "^9.0.0",
"lacchain-key-manager": "^0.0.2",
"lacchain-key-manager": "^0.0.6",
"morgan": "^1.10.0",
"multer": "^1.4.4",
"nodemailer": "^6.7.3",
Expand Down
3 changes: 2 additions & 1 deletion src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,5 +208,6 @@ export const {
LACCHAIN_IDENTITY_IS_DEPENDENT_SERVICE,
SECP256K1_SIGN_ETHEREUM_TRANSACTION,
SECP256K1_SIGN_LACCHAIN_TRANSACTION,
ED25519_CREATE_KEY
ED25519_CREATE_KEY,
P256_CREATE_KEY
} = process.env;
8 changes: 6 additions & 2 deletions src/constants/errorMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export enum ErrorsMessages {
INVALID_EXPIRATION_DAYS = 'Valid days must be greater than zero',
INVALID_JWK_TYPE = 'Invalid Jwk type',
// eslint-disable-next-line max-len
UNSUPPORTED_JWK_CREATION_FOR_TYPE = 'The type of jwk for creation is not supported yet, valid type: "secp256k1"',
UNSUPPORTED_JWK_CREATION_FOR_TYPE = 'The type of jwk for creation is not supported yet, valid type: "secp256k1" or "secp256r1"',
INVALID_VM_RELATION_TYPE = 'Invalid verification method relation type',
UNSUPPORTED_ATTRIBUTE_ENCODING_METHOD = 'Unsupported attribute encoding',
INVALID_DELEGATE_TYPE = 'Invalid delegate type',
Expand All @@ -46,7 +46,11 @@ export enum ErrorsMessages {
UNEXPECTED_RESPONSE_IN_SUCCESSFUL_TRANSACTION_ERROR = 'Transaction was successfully completed but received an unexpected response',
UNSUPPORTED_CHAIN_ID_IN_DID = 'Unsupported chainId was found in DID',
UNSUPPORTED_DID_TYPE = 'Unsupported DID type',
UNSUPPORTED_DID_VERSION = 'Unsupported DID version'
UNSUPPORTED_DID_VERSION = 'Unsupported DID version',
// eslint-disable-next-line max-len
PUBLIC_KEY_COMPRESSED_FORMAT_ERROR = 'Unexpected public key format, expected compressed format',
// eslint-disable-next-line max-len
PUBLIC_KEY_UNCOMPRESSED_FORMAT_ERROR = 'Unexpected public key format, expected uncompressed format'
}

export const Errors = {
Expand Down
2 changes: 1 addition & 1 deletion src/dto/did-lac/attributeDTO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class NewAttributeDTO {

export class NewJwkAttributeDTO extends NewAttributeDTO {
@IsString()
jwkType!: 'secp256k1';
jwkType!: 'secp256k1' | 'secp256r1';
}

export class RevokeAttributeDTO {
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/did-lacchain/did-lacchain.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export interface INewAttribute {
}

export interface INewJwkAttribute extends INewAttribute {
jwkType: 'secp256k1';
jwkType: 'secp256k1' | 'secp256r1';
}

export interface IAccountIdAttribute {
Expand Down
2 changes: 2 additions & 0 deletions src/interfaces/key/key.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ export interface IECKey {
address: string;
publicKey: string;
type: string;
x?: string;
y?: string;
}
91 changes: 71 additions & 20 deletions src/services/did-lac/did.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,31 +159,82 @@ export abstract class DidService implements DidLacService {
}
async addNewJwkAttribute(attribute: INewJwkAttribute): Promise<any> {
if (attribute.jwkType == 'secp256k1') {
const key = await this.keyManagerService.createSecp256k1Key();
const x = Buffer.from(key.publicKey.replace('0x', ''), 'hex').toString(
'base64url'
);
const ecJwk: EcJwk = {
kty: 'EC',
x,
crv: 'secp256k1'
};
const ecJwkAttribute: IJwkEcAttribute = {
did: attribute.did,
ecJwk,
validDays: attribute.validDays,
relation: attribute.relation
};
const r: INewJwkAttributeCreationResponse = {
...(await this.addEcJwkAttribute(ecJwkAttribute)),
jwk: ecJwk
};
return r;
return this.addNewSecp256k1JwkAttribute(attribute);
} else if (attribute.jwkType == 'secp256r1') {
return this.addNewSecp256r1JwkAttribute(attribute);
}
const message = ErrorsMessages.UNSUPPORTED_JWK_CREATION_FOR_TYPE;
this.log.info(message);
throw new BadRequestError(message);
}

async addNewSecp256k1JwkAttribute(attribute: INewJwkAttribute): Promise<any> {
const key = await this.keyManagerService.createSecp256k1Key();
// invariant verification
const pubKey = key.publicKey.replace('0x', '');
if (pubKey.length !== 66 || !pubKey.startsWith('02')) {
throw new BadRequestError(
ErrorsMessages.PUBLIC_KEY_COMPRESSED_FORMAT_ERROR
);
}
const x = Buffer.from(key.publicKey.replace('0x02', ''), 'hex').toString(
'base64url'
);
const ecJwk: EcJwk = {
kty: 'EC',
x,
crv: 'secp256k1'
};
const ecJwkAttribute: IJwkEcAttribute = {
did: attribute.did,
ecJwk,
validDays: attribute.validDays,
relation: attribute.relation
};
const r: INewJwkAttributeCreationResponse = {
...(await this.addEcJwkAttribute(ecJwkAttribute)),
jwk: ecJwk
};
return r;
}

async addNewSecp256r1JwkAttribute(attribute: INewJwkAttribute): Promise<any> {
const key = await this.keyManagerService.createP256Key();
// invariant verification
const pubKey = key.publicKey.replace('0x', '');
if (pubKey.length !== 130 || !pubKey.startsWith('04')) {
throw new BadRequestError(
ErrorsMessages.PUBLIC_KEY_UNCOMPRESSED_FORMAT_ERROR
);
}
const pubKeyNoPrefix = key.publicKey.replace('04', '');
const x = Buffer.from(pubKeyNoPrefix.substring(0, 64), 'hex').toString(
'base64url'
);
const y = Buffer.from(pubKeyNoPrefix.substring(64, 128), 'hex').toString(
'base64url'
);

const ecJwk: EcJwk = {
kty: 'EC',
x,
y,
crv: 'P-256'
};
console.log(ecJwk);
const ecJwkAttribute: IJwkEcAttribute = {
did: attribute.did,
ecJwk,
validDays: attribute.validDays,
relation: attribute.relation
};
const r: INewJwkAttributeCreationResponse = {
...(await this.addEcJwkAttribute(ecJwkAttribute)),
jwk: ecJwk
};
return r;
}

async addRsaJwkAttribute(jwkRsaAttribute: IJwkRsaAttribute): Promise<any> {
// TODO: validate RSA params
const { kty } = jwkRsaAttribute.rsaJwk;
Expand Down
31 changes: 30 additions & 1 deletion src/services/external/key-manager.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
SECP256K1_SIGN_ETHEREUM_TRANSACTION,
SECP256K1_SIGN_LACCHAIN_TRANSACTION,
log4TSProvider,
ED25519_CREATE_KEY
ED25519_CREATE_KEY,
P256_CREATE_KEY
} from '../../config';
import {
IEthereumTransaction,
Expand All @@ -24,6 +25,7 @@ import { IECKey } from 'src/interfaces/key/key.interface';
export class KeyManagerService {
public createSecp256k1Key: () => Promise<IECKey>;
public createEd25519Key: () => Promise<IECKey>;
public createP256Key: () => Promise<IECKey>;
public signEthereumTransaction: (
ethereumTransaction: IEthereumTransaction
) => Promise<ISignedTransaction>;
Expand All @@ -35,6 +37,7 @@ export class KeyManagerService {
// eslint-disable-next-line max-len
private secp256k1SignLacchainTransactionService: Secp256k1SignLacchainTransactionService | null;
private generic25519Service: ECService | null;
private p256KeyService: ECService | null;
log = log4TSProvider.getLogger('KeyManagerService');
constructor() {
if (LACCHAIN_IDENTITY_IS_DEPENDENT_SERVICE !== 'true') {
Expand All @@ -56,6 +59,10 @@ export class KeyManagerService {
this.createEd25519Key = this.createEd25519KeyByLib;
const SS = require('lacchain-key-manager').Generic25519DbService;
this.generic25519Service = new SS('ed25519');

this.createP256Key = this.createP256KeyByLib;
const TT = require('lacchain-key-manager').P256DbService;
this.p256KeyService = new TT();
} else {
this.log.info('Configuring key-manager external service connection');
this.secp256k1Service = null;
Expand All @@ -71,6 +78,9 @@ export class KeyManagerService {

this.generic25519Service = null;
this.createEd25519Key = this.createEd25519KeyByExternalService;

this.p256KeyService = null;
this.createP256Key = this.createP256KeyByExternalService;
}
}
async createSecp256k1KeyByLib(): Promise<IECKey> {
Expand Down Expand Up @@ -110,6 +120,25 @@ export class KeyManagerService {
return (await result.json()) as IECKey;
}

async createP256KeyByLib(): Promise<IECKey> {
return (await this.p256KeyService?.createKey()) as IECKey;
}

async createP256KeyByExternalService(): Promise<IECKey> {
const result = await fetch(`${KEY_MANAGER_BASE_URL}${P256_CREATE_KEY}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
console.log('status', result.status);
if (result.status !== 200) {
console.log(await result.text());
throw new InternalServerError(ErrorsMessages.CREATE_KEY_ERROR);
}
return (await result.json()) as IECKey;
}

async signEthereumTransactionByLib(
ethereumTransaction: IEthereumTransaction
): Promise<ISignedTransaction> {
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5402,10 +5402,10 @@ koa@^2.8.2:
type-is "^1.6.16"
vary "^1.1.2"

lacchain-key-manager@^0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/lacchain-key-manager/-/lacchain-key-manager-0.0.2.tgz#e9996ad66bdbf52e4db3148390a09dff630413b7"
integrity sha512-8qDeQUYHgZylcPQDkKc3N6eprVUlp0vCH+4GsH+iznZ6HlWhhdghMgEgYwSq1jlmM9L/jBos+m7m1iWBDWoQbg==
lacchain-key-manager@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/lacchain-key-manager/-/lacchain-key-manager-0.0.6.tgz#2d4c3bd175ab11332a7f4657d70438ee47bf7f18"
integrity sha512-RRuazKwiLniOuGE/PmriZqjXbOjBYIe9a1vxCCHeJGnVs6mVp3dD9MnDArszUd+xiJLL4L9CLa0hzTOYZjXOhA==
dependencies:
"@lacchain/gas-model-provider" "^1.0.1"
DIDComm-js "git+https://github.com/decentralized-identity/DIDComm-js.git"
Expand Down

0 comments on commit 6b33c68

Please sign in to comment.