-
-
Notifications
You must be signed in to change notification settings - Fork 72
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
Encrypted keys should provide a public key to decrypt encoded metadata #178
Comments
Related to #173. |
Convo with the founder of Timing,
|
I've removed mentions of the old encrypted licensing scheme from the docs. The old scheme is being used, so we'll need to add logic to account for older policies using the v1 scheme and continue to generate licenses with that scheme and not the new one. We can add an attribute to the policy like |
Add an attribute like Or maybe just a scalar hash like |
Encryption fields should not be able to be changed after creation. |
Having second thoughts on this, as it introduces a lot of complexity. May just write an example implementation in Swift using Keygen and protobufs for offline license support. |
I think the easiest way to implement this would be to allow an arbitrary string to be passed as a key, like we're doing now, and then encrypt the key with the account's private key. The encrypted key can then be decoded using the account's public key to retrieve any encoded data, e.g. JSON, etc. We need to prioritize, as this would allow offline licensing to be easier to implement. |
Max key size should be |
Thought: Maybe use AES for |
To support large license key data, we need to use AES. I think we should allow multiple encryption schemes, so the customer can opt-in to whichever fits their use case the best:
And then It should not be able to be changed. |
Using AES: require 'openssl'
require 'base64'
data = "Very, very confidential data\n" * 100
cipher = OpenSSL::Cipher::AES256.new :CBC
cipher.encrypt
key = cipher.random_key
iv = cipher.random_iv
encrypted = cipher.update(data) + cipher.final
decipher = OpenSSL::Cipher::AES256.new :CBC
decipher.decrypt
decipher.key = key
decipher.iv = iv
plain = decipher.update(encrypted) + decipher.final
puts "key = #{Base64.strict_encode64(key)}"
puts "iv = #{Base64.strict_encode64(iv)}"
puts "match = #{data == plain}" |
I don’t like the idea of using AES, actually. It opens up the possibility of keygens being created, and rather easily at that. |
Or we could just sign keys and skip embedded metadata… or add a separate (We should do this later on.) |
Potential customer, Serveo, who seems to want the signed keys (good validation to keep it). |
Example setup for showcasing signed keys: Serverconst crypto = require('crypto')
// License payload
const payload = {
key: crypto.randomBytes(16).toString('hex'),
customer: '[email protected]',
allowances: 3
}
// Convert JSON key payload into a buffer and then encode into base64
const key = Buffer.from(JSON.stringify(payload)).toString('base64')
// TODO(ezekg) Store license key in Keygen using the RSA_2048_SIGN encryption
// scheme, then encode into a license file along with the key's
// generated RSA signature for verification purposes.
const sig = ''
// Combine key and signature into a "license file"
const licenseFile = `${key}:${sig}`
// TODO(ezekg) Deliver license file to customer
const hex = Buffer.from(licenseFile).toString('hex') Clientconst { KEYGEN_PUBLIC_KEY } = process.env
const crypto = require('crypto')
const chalk = require('chalk')
// Decode the license file's contents
const [key, sig] = licenseFile.split(':')
// Verify the license key's contents
try {
const verifier = crypto.createVerify('sha256')
verifier.write(key)
verifier.end()
const v = verifier.verify(KEYGEN_PUBLIC_KEY, sig, 'base64')
if (!v) {
throw new Error('License key failed signature verification')
}
} catch (e) {
console.error(
chalk.red(e.message)
)
process.exit(1)
}
// Decode JSON key payload
const buf = Buffer.from(key, 'base64')
const obj = JSON.parse(buf.toString())
console.log(
chalk.green(JSON.stringify(obj, null, 2))
) |
For above: https://github.com/bushev/nodejs-license-file. ☝️ |
Encrypted keys should offer the ability to encode customer data within the license key, e.g. user email, name, etc. and should offer a public key which can be used to decode the data client-side. A private key would need to be generated alongside every encrypted policy, and encoded fields should be selectable by the account admin.
This would make encrypted keys more useful for e.g. offline use, where the public key can be stored client-side for offline license key validation.
The text was updated successfully, but these errors were encountered: