在開發程式的時候,我們可能會需要隱藏敏感的資料,讓一般使用者不會直接看到,例如流水序號、密碼、網頁Cookie等。這樣的資料通常都很小,可能只有數個位元組,但如果使用AES/DES加密,密文(也就是加密後的資料)都至少有16個位元組以上!實在不太適合用來加密這樣的少量資料。



在某些情況下,我們必須或是最好使用短密文。例如網址,人們通常偏好使用比較短的網址,甚至還會去使用「短網址」服務,因為短的網址其識別性更高,看起來更討喜,而且也更容易被傳播。另外就是條碼,條碼的物理空間和資料空間有限,過大的資料量會需要更大的面積來印條碼,因此想辦法減少條碼包含的資料量是很重要的課題。除此之外,需要透過網路傳輸的資料,如網頁Cookie等等,更短的資料量也可以讓傳輸速度變快,減少流量消耗。

ShortCrypt

ShortCrypt是一個跨程式語言的資料加解密函式庫,特點在於其密文只比明文(原始資料)還要大4個位元(半個位元組),非常適合用在需要短密文的條件下。此外,就算要加密的資料只有一位元組的差異,ShortCrypt所加密出來的密文也不會長得很像,不太需要擔心因為密文短就容易被猜出明文。

在Rust上使用ShortCrypt

Crates.io

Cargo.toml

short-crypt = "*"
使用方法

使用use關鍵字來將short_crypt這個crate底下的ShortCrypt結構體給引用到當前的程式範圍下,透過ShortCrypt結構體提供的new關聯函數,可以從參數傳入要用來加解密的密鑰字串,來建立出ShortCrypt結構實體。

use short_crypt::ShortCrypt;

fn main() {
    let sc = ShortCrypt::new("magickey");
}
加密

有了ShortCrypt結構實體之後,就可以使用encrypt方法來加密任意資料了!encrypt方法可以將透過參數傳入的資料,加密成由一個u8數值和一個Vec<u8>結構實體組成的元組(tuple)。前者即為那多出來的「4位元」,後者為加密後的資料,其大小等於透過參數傳入至encrypt方法的資料。把前後兩者合在一起就是密文了!

例如:

use short_crypt::ShortCrypt;

fn main() {
    let sc = ShortCrypt::new("magickey");

    assert_eq!((8, [216, 78, 214, 199, 157, 190, 78, 250].to_vec()), sc.encrypt("articles"));
}

如果要將密文轉成字串,除了可以自己寫程式處理外,可以使用ShortCrypt結構實體內建的encrypt_to_url_component方法將資料加密成能夠用在URL上的字串,或是用encrypt_to_qr_code_alphanumeric方法將資料加密成適合用在QR Code上的字串。

程式如下:

use short_crypt::ShortCrypt;

fn main() {
    let sc = ShortCrypt::new("magickey");

    assert_eq!("2E87Wx52-Tvo", sc.encrypt_to_url_component("articles"));
    assert_eq!("3BHNNR45XZH8PU", sc.encrypt_to_qr_code_alphanumeric("articles"));
}

如果想要將字串結果串接到現有的字串之後,可以使用encrypt_to_url_component_and_push_to_string或是encrypt_to_qr_code_alphanumeric_and_push_to_string方法。

解密

使用ShortCrypt結構實體的decrypt方法,可以解密從參數傳入的密文。不管明文是不是字串,解密結果都會是Vec<u8>結構實體。

例如:

use short_crypt::ShortCrypt;

fn main() {
    let sc = ShortCrypt::new("magickey");

    assert_eq!("articles".as_bytes().to_vec(), sc.decrypt(&(8, vec![216, 78, 214, 199, 157, 190, 78, 250])).unwrap());
}

如果密文是用剛才提過的encrypt_to_url_component方法和encrypt_to_qr_code_alphanumeric所產生出來的字串的話,則可以用decrypt_url_componentdecrypt_qr_code_alphanumeric方法來解密。

程式如下:

use short_crypt::ShortCrypt;

fn main() {
    let sc = ShortCrypt::new("magickey");

    assert_eq!("articles".as_bytes().to_vec(), sc.decrypt_url_component("2E87Wx52-Tvo").unwrap());
    assert_eq!("articles".as_bytes().to_vec(), sc.decrypt_qr_code_alphanumeric("3BHNNR45XZH8PU").unwrap());
}

如果要將解密出來的明文,直接串接到現有的Vec<u8>結構實體之後,可以使用decrypt_url_component_and_push_to_vec或是decrypt_qr_code_alphanumeric_and_push_to_vec方法。

在JavaScript/TypeScript上使用ShortCrypt

npmjs.com

npm 安裝指令

npm install short-crypt
使用方法

引入short-crypt後,接著使用new關鍵字來實體化出ShortCrypt的物件,可以從參數傳入要用來加解密的密鑰字串。

import { ShortCrypt } from "short-crypt";

const sc = new ShortCrypt(key);
加密

ShortCrypt物件有以下幾個與加密相關的方法:

  • encrypt:加密從參數傳入的資料,回傳一個擁有basebody欄位的物件,這個物件即為密文。
  • encryptToURLComponent:加密從參數傳入的資料,回傳一個能夠用在URL上的字串密文。
  • encryptToQRCodeAlphanumeric:加密從參數傳入的資料,回傳一個適合用在QR Code上的字串密文。

只有字串和Byte陣列(Uint8Array)可以被加密。

例如:

const cipher1 = sc.encryptToURLComponent(plainText);
const cipher2 = sc.encryptToQRCodeAlphanumeric(plainText);
解密

對應剛才提到的encryptencryptToURLComponentencryptToQRCodeAlphanumeric方法,ShortCrypt的物件有提供decryptdecryptURLComponentdecryptQRCodeAlphanumeric方法,可以解密那些不同形式的密文。

例如:

const result1 = sc.decryptURLComponent(cipher1);
const result2 = sc.decryptQRCodeAlphanumeric(cipher2);

在網頁瀏覽器上使用ShortCrypt

網頁原始碼

展示頁面