From dde7d9a7322ada9a9aa66d84e735e64f275bab48 Mon Sep 17 00:00:00 2001 From: fyears Date: Fri, 31 Dec 2021 20:55:13 +0800 Subject: [PATCH] fix enc base64url doc test --- docs/encryption.md | 15 ++++++++++----- src/misc.ts | 8 ++++++++ tests/encrypt.test.ts | 9 +++++---- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/docs/encryption.md b/docs/encryption.md index 8f8c488..5fb9958 100644 --- a/docs/encryption.md +++ b/docs/encryption.md @@ -15,15 +15,20 @@ The encryption algorithm is delibrately designed to be aligned with openssl form openssl enc -d -p -aes-256-cbc -pbkdf2 -iter 20000 -pass pass:somepassword -in ./sometext.txt.enc -out ./sometext.txt ``` -3. The file/directory path strings, are encrypted using openssl in binary mode and then `base32` is applied. +3. The file/directory path strings, are encrypted using openssl in binary mode and then `base64url without padding` is applied. Assuming the file path is `a-folder-文件夹/a-file-文件.md`, then the following commands are equivilent: ```bash - # pure string encryption then base32 - echo -n 'a-folder-文件夹/a-file-文件.md' | openssl enc -aes-256-cbc -pbkdf2 -iter 20000 -pass pass:mylongpassword | base32 -w 0 + # prepare the functions + # https://unix.stackexchange.com/questions/628842 + base64url::encode () { base64 -w0 | tr '+/' '-_' | tr -d '='; } + base64url::decode () { awk '{ if (length($0) % 4 == 3) print $0"="; else if (length($0) % 4 == 2) print $0"=="; else print $0; }' | tr -- '-_' '+/' | base64 -d; } - # pure string base32 then decryption - echo -n 'KNQWY5DFMRPV7UHRWVYFSHE2XVVVZCFN65SR7ETEKO5L6EYGXCVEPT4A2LVTW4W2ZHXWF3K22SVA562CCZ6SALARXJY6AAXXHLK5UOA=' | base32 -d -w 00 | openssl enc -d -aes-256-cbc -pbkdf2 -iter 20000 -pass pass:mylongpassword + # pure string encryption then base32 + echo -n 'a-folder-文件夹/a-file-文件.md' | openssl enc -aes-256-cbc -pbkdf2 -iter 20000 -pass pass:mylongpassword | base64url::encode + + # pure string base64url then decryption + echo -n 'U2FsdGVkX19tNkdFL5rZeHxbe7FL-Pp5mkZJkDNFJWFT6lldZlfa57j0C_cKn0I3PZ9YDvOkyoKqfF6lbn0_yg' | base64url::decode | openssl enc -d -aes-256-cbc -pbkdf2 -iter 20000 -pass pass:mylongpassword ``` 4. The directory is considered as special "0-byte" object on remote s3. So this meta infomation may be easily guessed if some third party can access the remote bucket. diff --git a/src/misc.ts b/src/misc.ts index 6d80b7c..c0537c3 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -114,6 +114,14 @@ export const base64ToBase32 = (a: string) => { return base32.stringify(Buffer.from(a, "base64")); }; +export const base64ToBase64url = (a: string, pad: boolean = false) => { + let b = a.replace(/\+/g, "-").replace(/\//g, "_"); + if (!pad) { + b = b.replace(/=/g, ""); + } + return b; +}; + /** * iOS Safari could decrypt string with invalid password! * So we need an extra way to test the decrypted result. diff --git a/tests/encrypt.test.ts b/tests/encrypt.test.ts index 0bdedb1..a6415ad 100644 --- a/tests/encrypt.test.ts +++ b/tests/encrypt.test.ts @@ -2,12 +2,13 @@ import * as fs from "fs"; import * as path from "path"; import * as chai from "chai"; import chaiAsPromised from "chai-as-promised"; -import { base64ToBase32, bufferToArrayBuffer } from "../src/misc"; +import { base64ToBase64url, bufferToArrayBuffer } from "../src/misc"; import { decryptArrayBuffer, decryptBase32ToString, encryptArrayBuffer, encryptStringToBase32, + encryptStringToBase64url, } from "../src/encrypt"; chai.use(chaiAsPromised); @@ -52,7 +53,7 @@ describe("Encryption tests", () => { ).toString("utf-8"); const password = "somepassword"; const saltHex = "8302F586FAB491EC"; - const enc = await encryptStringToBase32( + const enc = await encryptStringToBase64url( fileContent, password, undefined, @@ -65,9 +66,9 @@ describe("Encryption tests", () => { const opensslBase64Res = "U2FsdGVkX1+DAvWG+rSR7BPXMnlvSSVGMdjsx7kE1CTH+28P+yAZRdDGgFWMGkMd"; // we output base32, so we need some transformation - const opensslBase32Res = base64ToBase32(opensslBase64Res); + const opensslBase64urlRes = base64ToBase64url(opensslBase64Res); - expect(enc).equal(opensslBase32Res); + expect(enc).equal(opensslBase64urlRes); }); it("should encrypt binary file and get the same result as openssl", async () => {