Skip to content

Commit

Permalink
Move private keys to home dir (#165)
Browse files Browse the repository at this point in the history
* Change private keys dir

* Update docs and organize the code

* restore test folder and remove getPrivateKeyFromFile func

* Fix lint

* Change const name
  • Loading branch information
felipe.fuerback authored Apr 11, 2024
1 parent dfb6571 commit 4d0dafe
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 60 deletions.
4 changes: 2 additions & 2 deletions chain-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
"@oclif/core": "^2",
"@oclif/plugin-help": "^2",
"axios": "^1.6.0",
"dotenv": "16.3.1",
"fablo": "^0.0.1",
"nanoid": "^3.3.6",
"tslib": "^2.6.2",
"dotenv": "16.3.1"
"tslib": "^2.6.2"
},
"devDependencies": {
"eslint-config-oclif": "^4",
Expand Down
5 changes: 2 additions & 3 deletions chain-cli/src/commands/init/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import path from "path";

import BaseCommand from "../../base-command";
import { execSync } from "../../exec-sync";
import { DEFAULT_PRIVATE_KEYS_DIR, generateKeys } from "../../galachain-utils";
import { generateKeys } from "../../galachain-utils";
import { getPathFileName } from "../../utils";

export default class Init extends BaseCommand<typeof Init> {
Expand Down Expand Up @@ -63,8 +63,7 @@ export default class Init extends BaseCommand<typeof Init> {
}
});

this.log(`Generating keys to ${args.path}/${DEFAULT_PRIVATE_KEYS_DIR}`);
await generateKeys(`${args.path}/${DEFAULT_PRIVATE_KEYS_DIR}`);
await generateKeys(args.path);

this.log(`Project template initialized at ${args.path}`);
} catch (error) {
Expand Down
34 changes: 0 additions & 34 deletions chain-cli/src/galachain-utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,40 +91,6 @@ describe("deployChaincode", () => {
expect(response.status).toEqual("CH_CREATED");
});

it("should read a file with a private key and get deployChaincode response", async () => {
// Given
axios.post = jest.fn().mockResolvedValue({
status: 201,
data: {
status: "CH_CREATED"
}
});

process.env = { ...process.env, DEV_PRIVATE_KEY: undefined };

const execSync = jest.spyOn(require("child_process"), "execSync");
execSync.mockImplementation(
() =>
'[{"contractName":"AppleContract"},{"contractName":"GalaChainToken"},{"contractName":"PublicKeyContract"}]'
);

jest
.spyOn(fs, "readFileSync")
.mockImplementation(() => "bf2168e0e2238b9d879847987f556a093040a2cab07983a20919ac33103d0d00");

const postDeployChaincodePrivateKey = {
privateKey: await getPrivateKey(undefined),
isTestnet,
imageTag
};

// When
const response = await deployChaincode(postDeployChaincodePrivateKey);

// Then
expect(response.status).toEqual("CH_CREATED");
});

it("should ask for private key and get deployChaincode response", async () => {
// Given
axios.post = jest.fn().mockResolvedValue({
Expand Down
49 changes: 29 additions & 20 deletions chain-cli/src/galachain-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ import { parseStringOrFileKey } from "./utils";

const ConfigFileName = ".galachainrc.json";
const PackageJsonFileName = "package.json";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const os = require("os");

export const DEFAULT_PRIVATE_KEYS_DIR = "keys";
export const DEFAULT_ADMIN_PRIVATE_KEY_NAME = "gc-admin-key";
export const DEFAULT_DEV_PRIVATE_KEY_NAME = "gc-dev-key";
const DEFAULT_PRIVATE_KEYS_DIR = ".gc-keys";
const DEFAULT_PUBLIC_KEYS_DIR = "keys";
const DEFAULT_ADMIN_PRIVATE_KEY_NAME = "gc-admin-key";
const DEFAULT_DEV_PRIVATE_KEY_NAME = "gc-dev-key";

export interface Config {
org: string;
Expand Down Expand Up @@ -140,27 +143,44 @@ export async function deployChaincode(params: { privateKey: string; isTestnet: b
return response.data;
}

export async function generateKeys(keysPath: string): Promise<void> {
export async function generateKeys(projectPath: string): Promise<void> {
const keysPath = path.join(projectPath, DEFAULT_PUBLIC_KEYS_DIR);

const adminPrivateKey = secp.utils.bytesToHex(secp.utils.randomPrivateKey());
const adminPublicKey = secp.utils.bytesToHex(secp.getPublicKey(adminPrivateKey));
const adminPublicKeyEthAddr = "gc-" + signatures.getEthAddress(adminPublicKey);

const devPrivateKey = secp.utils.bytesToHex(secp.utils.randomPrivateKey());
const devPublicKey = secp.utils.bytesToHex(secp.getPublicKey(devPrivateKey));
const devPublicKeyEthAddr = "gc-" + signatures.getEthAddress(devPublicKey);

fs.mkdir(`${keysPath}`, (err) => {
if (err) console.error(`Could not create a directory ${keysPath}. Error: ${err}`);
});

const adminPrivateKeyPath = path.join(os.homedir(), DEFAULT_PRIVATE_KEYS_DIR, adminPublicKeyEthAddr);
fs.mkdir(adminPrivateKeyPath, { recursive: true }, (err) => {
if (err) console.error(`Could not create a directory ${adminPrivateKeyPath}. Error: ${err}`);
});

const devPrivateKeyPath = path.join(os.homedir(), DEFAULT_PRIVATE_KEYS_DIR, devPublicKeyEthAddr);
fs.mkdir(devPrivateKeyPath, { recursive: true }, (err) => {
if (err) console.error(`Could not create a directory ${devPrivateKeyPath}. Error: ${err}`);
});

await writeFile(`${keysPath}/${DEFAULT_ADMIN_PRIVATE_KEY_NAME}.pub`, adminPublicKey);
await writeFile(`${keysPath}/${DEFAULT_ADMIN_PRIVATE_KEY_NAME}`, adminPrivateKey.toString());
await writeFile(`${keysPath}/${DEFAULT_DEV_PRIVATE_KEY_NAME}.pub`, devPublicKey);
await writeFile(`${keysPath}/${DEFAULT_DEV_PRIVATE_KEY_NAME}`, devPrivateKey.toString());

await writeFile(`${adminPrivateKeyPath}/${DEFAULT_ADMIN_PRIVATE_KEY_NAME}`, adminPrivateKey.toString());
await writeFile(`${devPrivateKeyPath}/${DEFAULT_DEV_PRIVATE_KEY_NAME}`, devPrivateKey.toString());

console.log(
`Public keys created at ${keysPath} directory. Private keys created at ${adminPrivateKeyPath} and ${devPrivateKeyPath} directory.`
);
}

export async function getPrivateKey(keysFromArg: string | undefined) {
return (
keysFromArg || process.env.DEV_PRIVATE_KEY || getPrivateKeyFromFile() || (await getPrivateKeyPrompt())
);
return keysFromArg || process.env.DEV_PRIVATE_KEY || (await getPrivateKeyPrompt());
}

export async function overwriteApiConfig(contracts: string, channel: string, chaincodeName: string) {
Expand Down Expand Up @@ -200,17 +220,6 @@ export async function overwriteApiConfig(contracts: string, channel: string, cha
fs.writeFileSync(apiConfigPath, JSON.stringify(JSON.parse(apiConfigJson), null, 2));
}

function getPrivateKeyFromFile(): string | undefined {
try {
return fs.readFileSync(
`${process.cwd()}/${DEFAULT_PRIVATE_KEYS_DIR}/${DEFAULT_DEV_PRIVATE_KEY_NAME}`,
"utf8"
);
} catch (e) {
console.error(`Error reading file: ${e}`);
}
}

async function getPrivateKeyPrompt(): Promise<string> {
console.log(
"Private key not found. It should be provided as an argument, as an environment variable DEV_PRIVATE_KEY or as a file."
Expand Down
2 changes: 1 addition & 1 deletion docs/hackathon-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ For the first time we're able to provide you with the ability to deploy chaincod
galachain keygen gc-dev-key
```

The above command creates a private keys in `./gc-admin-key` and `./gc-dev1-key`, and public keys in `./gc-key.pub`, `./gc-dev-key.pub`. We need the content of `*.pub` files for chaincode admin user and for developer user who want to deploy. All the team members will use only one developer key, so make sure to share this with the other team member who want to deploy. Keep **private** keys safe, they will be needed later.
The above command creates a private keys in `./gc-admin-key` and `./gc-dev-key`, and public keys in `./gc-key.pub`, `./gc-dev-key.pub`. We need the content of `*.pub` files for chaincode admin user and for developer user who want to deploy. All the team members will use only one developer key, so make sure to share this with the other team member who want to deploy. Keep **private** keys safe, they will be needed later.

#### 3 Once we register your public keys, you will be able to connect your chaincode with GalaChain. To do it, navigate to the root directory of your chaincode and call the following command, providing path to developer private key:

Expand Down

0 comments on commit 4d0dafe

Please sign in to comment.