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: 🎸 added option to read OpenSSL key, EAS base64->base64url #311

Merged
merged 1 commit into from
Aug 23, 2023
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
10 changes: 10 additions & 0 deletions src/main/javascript/crypto/src/asn1/shemas/AttestationFramework.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ export class SubjectPublicKeyInfo {
@AsnProp({ type: AsnPropTypes.Any }) public null? = false;
}

export class PrivateKeyDataOpenSSL {
@AsnProp({ type: AsnPropTypes.Integer }) public one: number;
// @AsnProp({ type: AsnPropTypes.Any }) public algDescr2: Uint8Array;
@AsnProp({ type: AsnPropTypes.OctetString }) public privateKey: Uint8Array;
@AsnProp({ type: AsnPropTypes.ObjectIdentifier, context: 0 })
public algorithm: string;
@AsnProp({ type: AsnPropTypes.BitString, context: 1 })
public publicKey: Uint8Array;
}

export class PrivateKeyData {
@AsnProp({ type: AsnPropTypes.Integer }) public one: number;
// @AsnProp({ type: AsnPropTypes.Any }) public algDescr2: Uint8Array;
Expand Down
8 changes: 4 additions & 4 deletions src/main/javascript/crypto/src/eas/EasTicketAttestation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {BigNumber, ethers, Signer} from "ethers";
import {AttestationCrypto} from "../libs/AttestationCrypto";
import {AsnParser, AsnProp, AsnPropTypes, AsnSerializer} from "@peculiar/asn1-schema";
import {defaultAbiCoder, joinSignature} from "ethers/lib/utils";
import {hexStringToUint8, uint8tohex} from "../libs/utils";
import {base64UrltoBase64, base64toBase64Url, hexStringToUint8, uint8tohex} from "../libs/utils";
import {OffchainAttestationParams} from "@ethereum-attestation-service/eas-sdk/dist/offchain/offchain";
import {Attestable} from "../libs/Attestable";
import {AttestableObject} from "../libs/AttestableObject";
Expand Down Expand Up @@ -202,7 +202,7 @@ export class EasTicketAttestation extends AttestableObject implements Attestable


getEncoded(){
return zipAndEncodeToBase64(this.getEasJson());
return base64toBase64Url(zipAndEncodeToBase64(this.getEasJson()));
}

// TODO: Return ID based on decoded data
Expand Down Expand Up @@ -332,10 +332,10 @@ export class EasTicketAttestation extends AttestableObject implements Attestable
}

loadFromEncoded(
base64: string,
base64url: string,
keys?: KeysArray,
commitmentSecret?: string){
const decoded = decodeBase64ZippedBase64(base64);
const decoded = decodeBase64ZippedBase64(base64UrltoBase64(base64url));

this.loadEasAttestation(decoded.sig as SignedOffchainAttestation, keys, commitmentSecret)
}
Expand Down
135 changes: 135 additions & 0 deletions src/main/javascript/crypto/src/keyPair.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/**
* @jest-environment jsdom
*/

import {
bnToUint8,
hexStringToUint8,
stringToArray,
uint8arrayToBase64,
uint8tohex,
testsLogger, base64ToUint8array, hexStringToBase64
} from './libs/utils';
import {readFileSync} from "fs";
import {KeyPair} from "./libs/KeyPair";
import {Authenticator} from "./Authenticator";
import {Asn1Der} from "./libs/DerUtility";
import {DEBUGLEVEL} from "./config";


const querystring = require('querystring');

const PREFIX_PATH = '../../../../build/test-results/';

let useAttestRes: string,
sessionKey: KeyPair,
session2Key: KeyPair,
userKey: KeyPair,
userPubKey: KeyPair,
attestorPubKey: KeyPair,
attestorKey: KeyPair,
safeconnectKey: KeyPair,

senderKey: KeyPair,
senderPubKey: KeyPair,

sessionSignature: Uint8Array,
useAttestationJson: string,
attestationRequestJson: string,
requestAttestAndUsage: string,
magicLink: string,

magicLinkPublicPEM: string,
magicLinkPrivatePEM: string,

useRequestAttestationJson: string;
let sessionMessage = "message";
let email = "test@test.ts";
let type = "mail";
let WEB_DOMAIN = "http://wwww.hotelbogota.com";
let ATTESTOR_DOMAIN = "http://wwww.attestation.id";

describe("Utils tests", () => {
test('uint8tohex test', () => {
expect(uint8tohex(new Uint8Array([1,2]))).toBe("0102")
})
});

describe("Read keys and files", () => {

attestationRequestJson = readFileSync(PREFIX_PATH + 'attestation-request.json', 'utf8');
attestationRequestJson = attestationRequestJson.split(/\r?\n/).join('');

const userPrivPEM = readFileSync(PREFIX_PATH + 'user-priv.pem', 'utf8');
userKey = KeyPair.privateFromPEM(userPrivPEM);

const userPubPEM = readFileSync(PREFIX_PATH + 'user-pub.pem', 'utf8');
userPubKey = KeyPair.publicFromBase64orPEM(userPubPEM);

const senderPubPEM = readFileSync(PREFIX_PATH + 'sender-pub.pem', 'utf8');
senderPubKey = KeyPair.publicFromBase64orPEM(senderPubPEM);

const attestorPubPEM = readFileSync(PREFIX_PATH + 'attestor-pub.pem', 'utf8');
attestorPubKey = KeyPair.publicFromBase64orPEM(attestorPubPEM);

const attestorPrivPEM = readFileSync(PREFIX_PATH + 'attestor-priv.pem', 'utf8');
attestorKey = KeyPair.privateFromPEM(attestorPrivPEM);

const sessionPrivPEM = readFileSync(PREFIX_PATH + 'session-priv.pem', 'utf8');
sessionKey = KeyPair.privateFromPEM(sessionPrivPEM);

const senderPrivPEM = readFileSync(PREFIX_PATH + 'sender-priv.pem', 'utf8');
senderKey = KeyPair.privateFromPEM(senderPrivPEM);

const session2PrivPEM = readFileSync(PREFIX_PATH + 'session-priv2.pem', 'utf8');
session2Key = KeyPair.privateFromPEM(session2PrivPEM);

const safeconnectIssuerPubKeyPem = readFileSync(PREFIX_PATH + 'key-ec.txt', 'utf8');
safeconnectKey = KeyPair.publicFromBase64orPEM(safeconnectIssuerPubKeyPem);

useAttestationJson = readFileSync(PREFIX_PATH + 'use-attestation.json', 'utf8');

magicLink = readFileSync(PREFIX_PATH + 'mah@mah.com.url', 'utf8');

useRequestAttestationJson = readFileSync(PREFIX_PATH + 'use-and-request-attestation.json', 'utf8');

magicLink = readFileSync(PREFIX_PATH + 'mah_v2@mah.com.url', 'utf8');
magicLinkPrivatePEM = readFileSync('../../../../src/test/data/namedEcPrivKey.pem', 'utf8');
magicLinkPublicPEM = readFileSync('../../../../src/test/data/namedEcPubKey.pem', 'utf8');

test('Read keys test ok', () => {
expect(userPubKey.getPublicKeyAsHexStr()).toBe(userKey.getPublicKeyAsHexStr());
})
});

describe("read public key", () => {
// Standard PKCS stored key
const pubKeyPem1 = readFileSync(PREFIX_PATH + 'ticket-issuer-key.pem', 'utf8');
let addr1 = "0x94085A072E5481D64D6E2165268801B87A362B64";
// Pure base64 dump
const keyFile2 = 'MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEOt9mWLpQVOxiOvswFK4GGI0oOZ2GqS2Q6ec0AWIeuVoCuTD+atppPvjMgNLg9qQzJxsDW3zLxnOPFWO/Decnag==';
let addr2 = "0x17C0B3B51A75F1A001F255A7CAD4FA45529CAC20";


test('read 2 keys', async () => {
let key1 = Authenticator.decodePublicKey(pubKeyPem1);
expect(key1.getAddress().toLocaleLowerCase()).toBe(addr1.toLocaleLowerCase());

let key2 = Authenticator.decodePublicKey(keyFile2);
expect(key2.getAddress().toLocaleLowerCase()).toBe(addr2.toLocaleLowerCase());
})
})

describe("read private key", () => {

let opensslKey = "MHQCAQEEIF4H530+T2FFQjMI0hkaMzR5DfotHzXbhAcq+OxjcM5WoAcGBSuBBAAKoUQDQgAEYOCWsqPOp9lirOB9xIO5zIepnAoIgPfWwRG06XonF8+BdHrPMqe1DzsEwsuIDpVxB9fEpZVbVPkPurFYDk8KAQ=="
// Standard PKCS stored key

test('read key', async () => {
let key = KeyPair.privateFromPEM(opensslKey)
expect(key.getAddress().toLowerCase()).toBe("0xCE88748AEDF95313D96559AB39254F332DFE8F9C".toLowerCase())
})


})

25 changes: 20 additions & 5 deletions src/main/javascript/crypto/src/libs/KeyPair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {AsnParser} from "@peculiar/asn1-schema";
import {
PrivateKeyData,
PrivateKeyInfo, PublicKeyInfoValue,
SubjectPublicKeyInfo
SubjectPublicKeyInfo, PrivateKeyDataOpenSSL
} from "../asn1/shemas/AttestationFramework";
import {ethers} from "ethers";
import {Signature} from "../asn1/shemas/Signature";
Expand Down Expand Up @@ -206,11 +206,26 @@ export class KeyPair {

static privateFromPEM(pem: string): KeyPair {
const receiverPrivUint8 = base64ToUint8array(pem);
let privateKeyObj: PrivateKeyInfo = AsnParser.parse(receiverPrivUint8, PrivateKeyInfo);
return KeyPair.privateFromKeyInfo(privateKeyObj);
}
try {
let privateKeyObj: PrivateKeyInfo = AsnParser.parse(receiverPrivUint8, PrivateKeyInfo);
return KeyPair.privateFromKeyInfo(privateKeyObj);
} catch(e){
// try to decode OpenSSL format
}
let privateKeyObj: PrivateKeyDataOpenSSL = AsnParser.parse(receiverPrivUint8, PrivateKeyDataOpenSSL);

let me = new this();

if (privateKeyObj.algorithm === "1.3.132.0.10") {
me.algorithm = "secp256k1"
} else {
throw new Error(`Unknown algorithm "${privateKeyObj.algorithm}"`)
}

me.privKey = new Uint8Array(privateKeyObj.privateKey);
return me;

}

// Generate a private key
static async generateKeyAsync(): Promise<KeyPair> {
Expand Down Expand Up @@ -298,7 +313,7 @@ export class KeyPair {

getAddress(): string {
var pubPoint = this.getPublicKeyAsHexStr();
pubPoint = pubPoint.substr(2);
pubPoint = pubPoint.substring(2);
let hash = sha3.keccak256(hexStringToArray(pubPoint));
return "0x" + hash.substr(-40).toUpperCase();
}
Expand Down
10 changes: 8 additions & 2 deletions src/main/javascript/crypto/src/libs/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,14 @@ export function uint8arrayToBase64( bytes: Uint8Array ): string {

export function base64toBase64Url(base64: string): string {
return base64.split('/').join('_')
.split('+').join('-');
// .split('=').join('.');
.split('+').join('-')
.split('=').join('.');
}

export function base64UrltoBase64(base64Url: string): string {
return base64Url.split('_').join('/')
.split('-').join('+')
.split('.').join('=');
}

export function pemOrBase64Orbase64urlToString(base64str: string): string {
Expand Down