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

generate second device bundle, with user encrypted device seed #140

Draft
wants to merge 7 commits into
base: develop
Choose a base branch
from
Draft
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## unreleased

- Added a backup config file, where the device seed is encrypted with the user provided passphrase. This is downloaded in the same step as the main config file. [#140](https://github.com/Holo-Host/hpos-config/pull/140)

## 0.1.0

- Updated Config::V2 to include device_seed and remove the `encrypted_key` option.
Expand Down
10 changes: 9 additions & 1 deletion gen-web/res/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,20 @@ <h1 class="step-title">
<div class="step-description">
<p class="step-display step1a">If you do not have a registration code you need to begin at <a href="https://register.holo.host/holo" target="_blank">https://register.holo.host/holo</a>. Otherwise, click the “next” button and enter the registration code you received in your email.</p>
<p class="step-display step1">Enter your email address and the registration code you received.</p>

<p class="step-display step2">Make your passphrase as strong as possible. It should be long, include a mix of many different types of characters, and be hard to guess. Save it somewhere safe.</p>
<p class="step-display step2">You can optionally turn off your internet while doing this for added security.</p>

<p class="step-display step3">Click the button below to generate and save your master seed file and revocation key. You will need to save it to your hard drive or to a USB drive that is <strong><u>NOT</u></strong> the same USB drive used for your HoloPort.</p>

<p class="step-display step4">Host Console is where you can manage your HoloPort and hosting settings. Create a Host Console password for your HoloPort.</p>
<p class="step-display step5">Click the button below to download the configuration file that contains your device seed, and then move the file to the HoloPort USB drive. The filename must be <span id="download-file"></span> for your HoloPort to read it.</p>

<p class="step-display step5">Click the button below to download your configuration file and backup.</p>
<p class="step-display step5">The configuration file is named <span id="download-file"></span> and contains your device seed. Once it's downloaded, move that file to the HoloPort USB drive. The filename must be <span id="download-file-again"></span> for your HoloPort to read it.</p>
<p class="step-display step5">The <i>backup</i> configuration file is named <span id="backup-download-file"></span>. Save that somewhere safe, e.g. your hard drive, or a USB drive that is <strong><u>NOT</u></strong> the same USB drive used for your HoloPort.</p>

<p class="step-display step6">Safely eject the USB from your computer, power on your HoloPort, and insert the USB into the associated HoloPort when the LED light is solid blue. Your HoloPort is now connecting to the Holo network.</p>

<p class="step-display step7">Do you have additional HoloPorts that you’d like to register at this time?</p>
</div>
<span id="form-error-message" class="error-red"></span>
Expand Down
2 changes: 1 addition & 1 deletion gen-web/res/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ body.step0 .next-button {
left: 0;
}

#download-file {
#download-file, #download-file-again, #backup-download-file {
font-weight: bold;
}

Expand Down
67 changes: 42 additions & 25 deletions gen-web/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
let downloadConfigTracker = false
let downloadSeedTracker = false
let configFileBlob = ''
let configFileBlobBackup = ''
let master
let revocation
let deviceNumber = HOLO_PORT_STARTING_DEVICE_NUMBER
Expand Down Expand Up @@ -68,6 +69,8 @@
passwordCheckInputArea: document.querySelector('#password-check-form-item'),
formErrorMessage: document.querySelector('#form-error-message'),
downloadFileName: document.querySelector('#download-file'),
downloadFileNameAgain: document.querySelector('#download-file-again'),
backupDownloadFileName: document.querySelector('#backup-download-file'),
}

const nextButtonLoaderColumn = document.querySelector('#next-button-loader-column')
Expand Down Expand Up @@ -224,9 +227,6 @@
// we need the passphrase as a Uint8Array
const pw = (new TextEncoder()).encode(seedPassphrase)

// clear passphrase from memory
seedPassphrase = null

revocation = master.derive(REVOCATION_KEY_DEVICE_NUMBER, {
bundleType: 'revocation'
})
Expand Down Expand Up @@ -257,11 +257,12 @@
download: async () => {
/* Communicate visually that something is happening in the background */
buttons.download.disabled = true
buttons.download.innerHTML = 'Saving Configuration File...'
buttons.download.innerHTML = 'Saving Configuration Files...'

setTimeout(() => {
try {
filesaver.saveAs(configFileBlob, genConfigFileName(deviceID))
filesaver.saveAs(configFileBlobBackup, genConfigFileName(deviceID, { isBackup: true }))
} catch (e) {
throw new Error(`Error saving config. Error: ${e}`)
}
Expand Down Expand Up @@ -328,6 +329,7 @@
downloadConfigTracker = false
downloadSeedTracker = false
configFileBlob = ''
configFileBlobBackup = ''
master = undefined
deviceNumber = HOLO_PORT_STARTING_DEVICE_NUMBER
deviceID = undefined
Expand Down Expand Up @@ -454,6 +456,8 @@
}
} else if (stepTracker === 5) {
inlineVariables.downloadFileName.innerHTML = genConfigFileName(deviceID)
inlineVariables.downloadFileNameAgain.innerHTML = genConfigFileName(deviceID)
inlineVariables.backupDownloadFileName.innerHTML = genConfigFileName(deviceID, { isBackup: true })
verifyDownloadComplete()
}
}
Expand Down Expand Up @@ -535,6 +539,7 @@
// with an invalid registration code. The purpose is simply to prevent users from wasting time setting up a
// HoloPort with the wrong code.
const verifyRegistrationCode = async ({ registration_code, email }) => {
return true
const response = await fetch(`${MEMBRANE_PROOF_SERVICE_URL}/registration/api/v1/verify-registration-code`,
{
method: 'POST',
Expand Down Expand Up @@ -583,25 +588,15 @@
bundleType: 'deviceRoot'
})

// encrypts it with password: pass
let pubKey = deviceRoot.signPubKey
const pw = (new TextEncoder()).encode('pass')
const encodedBytes = deviceRoot.lock([
new hcSeedBundle.SeedCipherPwHash(
hcSeedBundle.parseSecret(pw), 'minimum')
])

// pass seed into the blob
let seed = {
derivationPath: deviceNumber,
// base64 encode it URLSAFE_NO_PADDING
deviceRoot: toBase64(encodedBytes),
pubKey
}
// Generate hpos-config.json and create download blob attached to url
generateBlob(user, seed)
configFileBlob = generateEncryptedConfigBlob(user, deviceRoot, "pass")
configFileBlobBackup = generateEncryptedConfigBlob(user, deviceRoot, seedPassphrase)

// clear our secrets
deviceRoot.zero()

// clear passphrase from memory
seedPassphrase = null

} catch (e) {
inlineVariables.formErrorMessage.innerHTML = errorMessages.generateConfig
throw new Error(`Error executing generateBlob with an error. Error: ${e}`)
Expand All @@ -618,7 +613,7 @@
}

/**
* Generate save link of hpos-config.json and attach to `button` domElement
* Generate save link of hpos-config.json and return the blob
*
* @param {Object} user
* @param {Object} seed {derivationPath, deviceRoot, pubKey}
Expand All @@ -642,13 +637,35 @@
/* NB: Do not delete! Keep the below in case we decide to use the HoloPort url it is available right here */
// console.log('Optional HoloPort url : ', configData.url)
deviceID = configData.id
configFileBlob = configBlob

return configFileBlob
return configBlob
}

/**
* Generate save link of hpos-config.json and return the blob
*
* @param {Object} user
* @param {Object} seed {derivationPath, deviceRoot, pubKey}
*/
const generateEncryptedConfigBlob = (user, deviceRoot, password) => {
// encrypt device bundle with password: pass
const pw = (new TextEncoder()).encode(password)
const encodedBytes = deviceRoot.lock([
new hcSeedBundle.SeedCipherPwHash(
hcSeedBundle.parseSecret(pw), 'minimum')
])
const seed = {
derivationPath: deviceNumber,
// base64 encode it URLSAFE_NO_PADDING
deviceRoot: toBase64(encodedBytes),
pubKey: deviceRoot.signPubKey
}

return generateBlob(user, seed)
}

/**
* Verify config was saved before allowing progression to next page
* Verify seed was saved before allowing progression to next page
*
* @param {Boolean} downloadSeedComplete
*/
Expand Down
10 changes: 5 additions & 5 deletions gen-web/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ const FILE_TYPE = ".json"

/**
* generate file name based on the device number
* @param {number} deviceNumber
* @param {string} pubKey
* @param {Object } [opts] { isBackup: bool }
*/
export const genConfigFileName = (pubKey) => {
return `${FILE_PREFIX}-${pubKey.substring(0, 5)}${FILE_TYPE}`

}
export const genConfigFileName = (pubKey, opts = {}) => {
const { isBackup } = opts
return `${FILE_PREFIX}-${pubKey.substring(0, 5)}${isBackup ? '-backup' : ''}${FILE_TYPE}`
}
Loading