@lryncloud/crypto
v1.0.0
Published
Zero-dependency Shangmi toolkit (SM2/SM3/SM4/SM9/ZUC/AES/RSA/EC/ChaCha20/OTP/X.509)
Maintainers
Readme
@lryncloud/crypto
Zero-dependency JavaScript cryptography toolkit for Shangmi algorithms and common application crypto workflows.
@lryncloud/crypto provides SM2, SM3, SM4, SM9, ZUC, AES, RSA, EC, ChaCha20/XChaCha20, OTP, X.509, ASN.1 and PEM/DER helpers from one package. It supports both ESM and CommonJS, ships TypeScript declarations, and is designed for JavaScript/TypeScript application code.
Features
- Shangmi / GM algorithms: SM2 sign/verify/encrypt/decrypt/key exchange, SM3 hash, SM4 ECB/CBC/CTR/CFB/OFB, SM9 sign/encrypt/KEM/key exchange, ZUC 128-EEA3/128-EIA3.
- Common crypto primitives: AES, AES-GCM, RSA, EC/ECDSA/ECDH, SHA, HMAC, ChaCha20, XChaCha20 and Poly1305.
- OTP workflows: HOTP, TOTP, OCRA and GMOTP.
- Encoding and certificate utilities: PEM/DER conversion, key import/export, ASN.1 DER helpers and X.509 certificate parsing/verification.
- Runtime friendly: zero runtime dependencies, ESM/CommonJS entry points, TypeScript declarations included.
Installation
npm install @lryncloud/cryptopnpm add @lryncloud/cryptoyarn add @lryncloud/cryptoQuick Start
ESM
import { sm3Hex, sm4EncryptCbc, sm4DecryptCbc } from "@lryncloud/crypto";
const key = "0123456789abcdeffedcba9876543210";
const iv = "000102030405060708090a0b0c0d0e0f";
console.log(sm3Hex("abc"));
const ciphertext = sm4EncryptCbc("hello", key, {
iv,
output: "hex",
});
const plaintext = sm4DecryptCbc(ciphertext, key, {
iv,
output: "utf8",
});
console.log(plaintext);CommonJS
const { Shangmi, hotpGenerate } = require("@lryncloud/crypto");
console.log(Shangmi.sm3Hex("abc"));
const code = hotpGenerate({
key: "3132333435363738393031323334353637383930",
keyFormat: "hex",
counter: 1,
});
console.log(code);API Overview
All public APIs are exported from the package root.
import {
Shangmi,
sm3Hex,
sm4EncryptCbc,
sm2Sign,
sm2Verify,
aesEncrypt,
rsaGenerateKeyPair,
totpGenerateCurrent,
} from "@lryncloud/crypto";The package exposes two usage styles:
- Function APIs for direct imports, such as
sm3Hex,sm4EncryptCbc,sm2Sign,aesEncrypt,totpGenerateCurrent. Shangmifacade for commonly used Shangmi and related helpers through static methods.
Shangmi Examples
SM3
import { sm3, sm3Hex } from "@lryncloud/crypto";
const digestBytes = sm3("abc");
const digestHex = sm3Hex("abc");
console.log(digestBytes);
console.log(digestHex);SM4 CBC
import { sm4EncryptCbc, sm4DecryptCbc } from "@lryncloud/crypto";
const key = "0123456789abcdeffedcba9876543210";
const iv = "000102030405060708090a0b0c0d0e0f";
const encrypted = sm4EncryptCbc("00112233445566778899aabbccddeeff", key, {
iv,
inputHex: true,
padding: false,
output: "hex",
});
const decrypted = sm4DecryptCbc(encrypted, key, {
iv,
padding: false,
output: "hex",
});
console.log(decrypted);SM2 Sign and Verify
import {
sm2DerivePublicKey,
sm2EncodePublicKey,
sm2Sign,
sm2Verify,
} from "@lryncloud/crypto";
const privateKeyHex = "3945208f7b2144b13f36e38ac6d39f95889393692860b51a42fb81ef4df7c5b8";
const publicKeyHex = sm2EncodePublicKey(sm2DerivePublicKey(privateKeyHex));
const signature = sm2Sign("message", privateKeyHex, {
id: "1234567812345678",
});
const valid = sm2Verify("message", signature, publicKeyHex, {
id: "1234567812345678",
});
console.log(valid);SM2 Encrypt and Decrypt
import {
sm2Decrypt,
sm2DerivePublicKey,
sm2EncodePublicKey,
sm2Encrypt,
} from "@lryncloud/crypto";
const privateKeyHex = "128b2fa8bd433c6c068c8d803dff79792a519a55171b1b650c23661d15897263";
const publicKeyHex = sm2EncodePublicKey(sm2DerivePublicKey(privateKeyHex));
const ciphertext = sm2Encrypt("hello", publicKeyHex, {
ciphertextLayout: "C1C3C2",
});
const plaintext = sm2Decrypt(ciphertext, privateKeyHex, {
ciphertextLayout: "auto",
output: "utf8",
});
console.log(plaintext);SM9
import {
sm9CreateMasterKeyPair,
sm9DeriveSignPrivateKey,
sm9Sign,
sm9Verify,
} from "@lryncloud/crypto";
const master = sm9CreateMasterKeyPair(
"0130e78459d78545cb54c587e02cf480ce0b66340f319f348a1d5b1f2dc5f401",
);
const userId = "Alice";
const signPrivateKey = sm9DeriveSignPrivateKey(userId, master.masterSecret);
const signature = sm9Sign("hello sm9", userId, signPrivateKey);
console.log(sm9Verify("hello sm9", userId, signature, master.masterPublic));ZUC 128-EEA3 / 128-EIA3
import { zucEea3Crypt, zucEia3Mac } from "@lryncloud/crypto";
const key = "000102030405060708090a0b0c0d0e0f";
const input = "00112233445566778899aabbccddeeff";
const encrypted = zucEea3Crypt(input, key, {
count: 0x398a59b4,
bearer: 0x15,
direction: 1,
bitLength: 128,
inputHex: true,
output: "hex",
});
const mac = zucEia3Mac(input, key, {
count: 0x398a59b4,
bearer: 0x15,
direction: 1,
bitLength: 128,
inputHex: true,
output: "hex",
});
console.log(encrypted, mac);Common Crypto Examples
AES-CBC
import { aesDecrypt, aesEncrypt, aesGenerateIv, aesGenerateKey } from "@lryncloud/crypto";
const key = aesGenerateKey({ bits: 128, output: "hex" });
const iv = aesGenerateIv({ mode: "cbc", output: "hex" });
const ciphertext = aesEncrypt("hello aes", key, {
bits: 128,
mode: "cbc",
iv,
output: "hex",
});
const plaintext = aesDecrypt(ciphertext, key, {
bits: 128,
mode: "cbc",
iv,
output: "utf8",
});
console.log(plaintext);RSA
import {
rsaDecrypt,
rsaEncrypt,
rsaGenerateKeyPair,
rsaSign,
rsaVerify,
} from "@lryncloud/crypto";
const { publicKeyPem, privateKeyPem } = rsaGenerateKeyPair({
modulusLength: 2048,
});
const ciphertext = rsaEncrypt("hello rsa", publicKeyPem, {
output: "base64",
});
console.log(rsaDecrypt(ciphertext, privateKeyPem, {
input: "base64",
output: "utf8",
}));
const signature = rsaSign("hello rsa", privateKeyPem, {
output: "base64",
});
console.log(rsaVerify("hello rsa", signature, publicKeyPem, {
input: "base64",
}));TOTP
import { totpGenerateCurrent, totpVerifyNow } from "@lryncloud/crypto";
const key = "3132333435363738393031323334353637383930";
const code = totpGenerateCurrent({
key,
keyFormat: "hex",
digits: 6,
});
const result = totpVerifyNow({
key,
keyFormat: "hex",
code,
window: 1,
});
console.log(code, result);Encoding, ASN.1 and X.509
import {
derToPem,
parseCertificate,
pemToDer,
} from "@lryncloud/crypto";
const { der } = pemToDer(certificatePem);
const pem = derToPem(der, "CERTIFICATE");
const certificate = parseCertificate(pem);
console.log(certificate);TypeScript
Type declarations are bundled with the package.
import { Sm2Signature, sm2Verify } from "@lryncloud/crypto";
const signature: Sm2Signature = {
r: "...",
s: "...",
};
const valid = sm2Verify("message", signature, "04...");Runtime Notes
- The package has no runtime dependencies.
- ESM uses
./src/index.js; CommonJS uses./src/index.cjs. - Most APIs accept
stringorUint8Arrayinput. - Hex/base64 handling is controlled by options such as
inputHex,inputBase64,input,output,keyFormatandtagInput. - Some RSA, EC and native crypto operations depend on the algorithms supported by the current Node.js/OpenSSL runtime.
Security Notes
- Use randomly generated production keys and IVs/nonces. Hard-coded values in this README are examples only.
- Do not reuse IVs/nonces with the same key for stream modes, GCM or ChaCha20-family APIs.
- Prefer authenticated encryption, such as AES-GCM or ChaCha20-Poly1305, when integrity protection is required.
- Validate protocol requirements before using low-level primitives directly.
Documentation
Additional guides and API notes are available in the repository:
docs/api/index.mddocs/guide/quickstart.mddocs/guide/usage.mddocs/guide/key-agreement.mddocs/guide/openssl-interop.md
License
Apache-2.0
