diff --git a/index.html b/index.html
index 30019e4..bf4c1e1 100644
--- a/index.html
+++ b/index.html
@@ -104,6 +104,12 @@
+
+
@@ -388,6 +394,31 @@
0xd2,
]);
},
+ async exportPrivateKey() {
+ try {
+ const response = await this.connection.exportPrivateKey();
+ console.log(response);
+ console.log(this.bytesToHex(response.privateKey));
+ } catch(e) {
+ alert(`Failed to export private key: ${e}`);
+ }
+ },
+ async importPrivateKey() {
+
+ const privateKeyHex = prompt("Enter private key encoded in hex");
+ if(!privateKeyHex){
+ return;
+ }
+
+ try {
+ const privateKey = this.hexToBytes(privateKeyHex);
+ await this.connection.importPrivateKey(privateKey);
+ alert("Private key imported!")
+ } catch(e) {
+ alert(`Failed to export private key: ${e}`);
+ }
+
+ },
async reboot() {
try {
await this.connection.reboot();
diff --git a/src/connection/connection.js b/src/connection/connection.js
index 86d8d5b..7129cc4 100644
--- a/src/connection/connection.js
+++ b/src/connection/connection.js
@@ -192,6 +192,19 @@ class Connection extends EventEmitter {
await this.sendToRadioFrame(data.toBytes());
}
+ async sendCommandExportPrivateKey() {
+ const data = new BufferWriter();
+ data.writeByte(Constants.CommandCodes.ExportPrivateKey);
+ await this.sendToRadioFrame(data.toBytes());
+ }
+
+ async sendCommandImportPrivateKey(privateKey) {
+ const data = new BufferWriter();
+ data.writeByte(Constants.CommandCodes.ImportPrivateKey);
+ data.writeBytes(privateKey);
+ await this.sendToRadioFrame(data.toBytes());
+ }
+
onFrameReceived(frame) {
// emit received frame
@@ -228,6 +241,10 @@ class Connection extends EventEmitter {
this.onBatteryVoltageResponse(bufferReader);
} else if(responseCode === Constants.ResponseCodes.DeviceInfo){
this.onDeviceInfoResponse(bufferReader);
+ } else if(responseCode === Constants.ResponseCodes.PrivateKey){
+ this.onPrivateKeyResponse(bufferReader);
+ } else if(responseCode === Constants.ResponseCodes.Disabled){
+ this.onDisabledResponse(bufferReader);
} else if(responseCode === Constants.PushCodes.Advert){
this.onAdvertPush(bufferReader);
} else if(responseCode === Constants.PushCodes.PathUpdated){
@@ -335,6 +352,18 @@ class Connection extends EventEmitter {
});
}
+ onPrivateKeyResponse(bufferReader) {
+ this.emit(Constants.ResponseCodes.PrivateKey, {
+ privateKey: bufferReader.readBytes(64),
+ });
+ }
+
+ onDisabledResponse(bufferReader) {
+ this.emit(Constants.ResponseCodes.Disabled, {
+
+ });
+ }
+
onSelfInfoResponse(bufferReader) {
this.emit(Constants.ResponseCodes.SelfInfo, {
type: bufferReader.readByte(),
@@ -1067,6 +1096,90 @@ class Connection extends EventEmitter {
});
}
+ exportPrivateKey() {
+ return new Promise(async (resolve, reject) => {
+ try {
+
+ // resolve promise when we receive private Key
+ const onPrivateKey = (response) => {
+ this.off(Constants.ResponseCodes.PrivateKey, onPrivateKey);
+ this.off(Constants.ResponseCodes.Err, onErr);
+ this.off(Constants.ResponseCodes.Disabled, onDisabled);
+ resolve(response);
+ }
+
+ // reject promise when we receive err
+ const onErr = () => {
+ this.off(Constants.ResponseCodes.PrivateKey, onPrivateKey);
+ this.off(Constants.ResponseCodes.Err, onErr);
+ this.off(Constants.ResponseCodes.Disabled, onDisabled);
+ reject();
+ }
+
+ // reject promise when we receive disabled
+ const onDisabled = () => {
+ this.off(Constants.ResponseCodes.PrivateKey, onPrivateKey);
+ this.off(Constants.ResponseCodes.Err, onErr);
+ this.off(Constants.ResponseCodes.Disabled, onDisabled);
+ reject("disabled");
+ }
+
+ // listen for events
+ this.once(Constants.ResponseCodes.PrivateKey, onPrivateKey);
+ this.once(Constants.ResponseCodes.Err, onErr);
+ this.once(Constants.ResponseCodes.Disabled, onDisabled);
+
+ // export private key
+ await this.sendCommandExportPrivateKey();
+
+ } catch(e) {
+ reject(e);
+ }
+ });
+ }
+
+ importPrivateKey(privateKey) {
+ return new Promise(async (resolve, reject) => {
+ try {
+
+ // resolve promise when we receive ok
+ const onOk = (response) => {
+ this.off(Constants.ResponseCodes.Ok, onOk);
+ this.off(Constants.ResponseCodes.Err, onErr);
+ this.off(Constants.ResponseCodes.Disabled, onDisabled);
+ resolve(response);
+ }
+
+ // reject promise when we receive err
+ const onErr = () => {
+ this.off(Constants.ResponseCodes.Ok, onOk);
+ this.off(Constants.ResponseCodes.Err, onErr);
+ this.off(Constants.ResponseCodes.Disabled, onDisabled);
+ reject();
+ }
+
+ // reject promise when we receive disabled
+ const onDisabled = () => {
+ this.off(Constants.ResponseCodes.Ok, onOk);
+ this.off(Constants.ResponseCodes.Err, onErr);
+ this.off(Constants.ResponseCodes.Disabled, onDisabled);
+ reject("disabled");
+ }
+
+ // listen for events
+ this.once(Constants.ResponseCodes.Ok, onOk);
+ this.once(Constants.ResponseCodes.Err, onErr);
+ this.once(Constants.ResponseCodes.Disabled, onDisabled);
+
+ // import private key
+ await this.sendCommandImportPrivateKey(privateKey);
+
+ } catch(e) {
+ reject(e);
+ }
+ });
+ }
+
}
export default Connection;
diff --git a/src/constants.js b/src/constants.js
index 9c45460..567aa02 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -34,6 +34,8 @@ class Constants {
GetBatteryVoltage: 20,
SetTuningParams: 21, // todo
DeviceQuery: 22,
+ ExportPrivateKey: 23,
+ ImportPrivateKey: 24,
}
static ResponseCodes = {
@@ -51,6 +53,8 @@ class Constants {
ExportContact: 11,
BatteryVoltage: 12,
DeviceInfo: 13,
+ PrivateKey: 14,
+ Disabled: 15,
}
static PushCodes = {