-
Notifications
You must be signed in to change notification settings - Fork 0
Format-preserving encryption capabilities #17
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
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
@@ -67,7 +67,7 @@ export class CrossmintApiService extends XMIFService { | |||
static createSignerInputSchema = z.object({ authId: z.string() }); | |||
static createSignerOutputSchema = z.object({}); | |||
|
|||
static sendOtpInputSchema = z.object({ otp: z.string() }); | |||
static sendOtpInputSchema = z.object({ otp: z.string(), publicKey: z.string() }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We add the public key for the TEE to derive the corresponding AES256 encryption key
ciphertext: ArrayBuffer, | ||
encapsulatedKey: ArrayBuffer, | ||
{ validateTeeSender }: { validateTeeSender: boolean } = { validateTeeSender: true } | ||
async decrypt<T extends Record<string, unknown>, U extends string | ArrayBuffer>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Integrated decrypt and decryptBase64 into a single function. Having both felt reduntant
async getEncryptionData(): Promise<EncryptionData> { | ||
// Key derivation | ||
|
||
private async deriveAES256EncryptionKey(): Promise<CryptoKey> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we derive the AES key for the FF1 algorithm!
this.assertInitialized(); | ||
// biome-ignore lint/style/noNonNullAssertion: asserted before | ||
return this.suite.kem.serializePublicKey(this.ephemeralKeyPair!.publicKey); | ||
private async serializePrivateKey(key: CryptoKey): Promise<ArrayBuffer> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We were using the kem serialization function but this had a problem in which, when we deserialized and reconstructed the keys, the usages of the key were not re'included, so it will fail later when trying to use it. That's why we built this custom serialization/deserialization functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sweet!
Looks great, but lets keep this in mind during our red team week.
@@ -54,7 +54,7 @@ export class AttestationService extends XMIFService { | |||
} | |||
|
|||
private async fetchAttestationDoc(): Promise<AttestationDocument> { | |||
const response = await fetch('https://tee-ts.onrender.com/attestation', {}); | |||
const response = await fetch('http://localhost:3001/attestation', {}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
intentional?
FF1 is a NIST-approved format preserving encryption (FPE) algorithm. This allows us to compute an AES256-encrypted OTP-like payload from an OTP-like payload!
This PR creates a
FPEService
that uses theencryptionService
to derive an AES256-GCM key from the shared secret that is present after ECDH exchange that we already performed for HPKE and uses that symmetric key to perform the OTP encryption.This is disabled. To be enabled by just uncommenting the line in the send OTP handler.
Tested it by running a local instance of the iframe and performing encryption-decryption within it! Will test end to end and enable when the corresponding part lands on the TEE-ts side
Tested the whole flow with the code in https://github.com/Paella-Labs/tee-ts/pull/3