@brashkie/signalis-core 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -638,6 +638,113 @@ declare function constantTimeEq(a: Buffer, b: Buffer): boolean;
638
638
  * is fine and avoids a NAPI hop.
639
639
  */
640
640
  declare function nativeSecureRandom(size: number): Buffer;
641
+ /**
642
+ * Base64 encoding (RFC 4648).
643
+ *
644
+ * Two variants are available:
645
+ * - **Standard** (`encode`/`decode`) — uses `A-Z a-z 0-9 + /` with `=` padding.
646
+ * Suitable for MIME, email, and general payloads.
647
+ * - **URL-safe** (`encodeUrlSafe`/`decodeUrlSafe`) — uses `-` and `_` instead
648
+ * of `+` and `/`, and omits padding. Safe for URLs, filenames, HTTP headers.
649
+ *
650
+ * @example
651
+ * ```ts
652
+ * const encoded = Base64.encode(Buffer.from('hello')); // "aGVsbG8="
653
+ * const decoded = Base64.decode(encoded); // <Buffer 68 65 6c 6c 6f>
654
+ * const url = Base64.encodeUrlSafe(Buffer.from('hello')); // "aGVsbG8" (no padding)
655
+ * ```
656
+ */
657
+ declare const Base64: Readonly<{
658
+ /**
659
+ * Encode bytes to standard Base64 (with `=` padding).
660
+ */
661
+ encode(input: Buffer): string;
662
+ /**
663
+ * Decode a standard Base64 string back to bytes.
664
+ *
665
+ * @throws {RangeError} on invalid characters, wrong length, or invalid padding.
666
+ */
667
+ decode(input: string): Buffer;
668
+ /**
669
+ * Encode bytes to URL-safe Base64 without padding.
670
+ * Uses `-` and `_` instead of `+` and `/`.
671
+ */
672
+ encodeUrlSafe(input: Buffer): string;
673
+ /**
674
+ * Decode a URL-safe Base64 string (no padding) back to bytes.
675
+ *
676
+ * @throws {RangeError} on invalid characters or wrong length.
677
+ */
678
+ decodeUrlSafe(input: string): Buffer;
679
+ }>;
680
+ /**
681
+ * Hex (Base16) encoding.
682
+ *
683
+ * - Encoding produces lowercase output by default.
684
+ * - Decoding is case-insensitive.
685
+ *
686
+ * @example
687
+ * ```ts
688
+ * const encoded = Hex.encode(Buffer.from([0xde, 0xad, 0xbe, 0xef])); // "deadbeef"
689
+ * const decoded = Hex.decode('DEADBEEF'); // <Buffer de ad be ef>
690
+ * Hex.isValid('deadbeef'); // true
691
+ * Hex.isValid('nope!'); // false
692
+ * ```
693
+ */
694
+ declare const Hex: Readonly<{
695
+ /**
696
+ * Encode bytes to a lowercase hex string.
697
+ */
698
+ encode(input: Buffer): string;
699
+ /**
700
+ * Encode bytes to an uppercase hex string.
701
+ * (Rare, but included for legacy protocols.)
702
+ */
703
+ encodeUpper(input: Buffer): string;
704
+ /**
705
+ * Decode a hex string to bytes. Case-insensitive.
706
+ *
707
+ * @throws {RangeError} on odd-length input or non-hex characters.
708
+ */
709
+ decode(input: string): Buffer;
710
+ /**
711
+ * Cheap validation: is this a well-formed hex string?
712
+ */
713
+ isValid(input: string): boolean;
714
+ }>;
715
+ /**
716
+ * UTF-8 encoding with strict validation.
717
+ *
718
+ * - `encode` converts a string to its UTF-8 byte representation.
719
+ * - `decode` validates strictly — invalid UTF-8 throws (does NOT silently
720
+ * replace with U+FFFD like `Buffer.toString('utf-8')` does).
721
+ * - `isValid` is a cheap check without allocation.
722
+ *
723
+ * @example
724
+ * ```ts
725
+ * const bytes = Utf8.encode('Hola 🦀'); // <Buffer 48 6f 6c 61 20 f0 9f a6 80>
726
+ * const text = Utf8.decode(bytes); // "Hola 🦀"
727
+ * Utf8.isValid(Buffer.from([0xff])); // false
728
+ * ```
729
+ */
730
+ declare const Utf8: Readonly<{
731
+ /**
732
+ * Encode a string to its UTF-8 byte representation.
733
+ */
734
+ encode(input: string): Buffer;
735
+ /**
736
+ * Decode UTF-8 bytes to a string.
737
+ *
738
+ * @throws {RangeError} on invalid UTF-8 (truncated multi-byte, lone surrogate,
739
+ * invalid start byte, etc.). Unlike `Buffer.toString('utf-8')`, this does
740
+ * NOT silently substitute U+FFFD.
741
+ */
742
+ decode(input: Buffer): string;
743
+ /**
744
+ * Check whether the given bytes are valid UTF-8.
745
+ */
746
+ isValid(input: Buffer): boolean;
747
+ }>;
641
748
 
642
749
  /**
643
750
  * Typed error classes for signalis-core.
@@ -938,7 +1045,7 @@ declare const AES_GCM_RECOMMENDED_MESSAGES_PER_KEY = 4294967296;
938
1045
  *
939
1046
  * Bumped on every release.
940
1047
  */
941
- declare const VERSION: "0.2.0";
1048
+ declare const VERSION: "0.4.0";
942
1049
 
943
1050
  /**
944
1051
  * Default export — provides all primitives and helpers under one namespace.
@@ -949,6 +1056,7 @@ declare const VERSION: "0.2.0";
949
1056
  *
950
1057
  * const kp = sc.Curve25519.generateKeyPair();
951
1058
  * const nonce = sc.secureRandom(12);
1059
+ * const b64 = sc.Base64.encode(nonce);
952
1060
  * ```
953
1061
  */
954
1062
  declare const SignalisCore: Readonly<{
@@ -1005,6 +1113,15 @@ declare const SignalisCore: Readonly<{
1005
1113
  KEY_SIZE: 32;
1006
1114
  IV_SIZE: 16;
1007
1115
  }>;
1116
+ ChaCha20Poly1305: Readonly<{
1117
+ encrypt(key: Buffer, nonce: Buffer, plaintext: Buffer): Buffer;
1118
+ decrypt(key: Buffer, nonce: Buffer, ciphertext: Buffer): Buffer;
1119
+ encryptWithAad(key: Buffer, nonce: Buffer, plaintext: Buffer, aad: Buffer): Buffer;
1120
+ decryptWithAad(key: Buffer, nonce: Buffer, ciphertext: Buffer, aad: Buffer): Buffer;
1121
+ KEY_SIZE: 32;
1122
+ NONCE_SIZE: 12;
1123
+ TAG_SIZE: 16;
1124
+ }>;
1008
1125
  HMAC: Readonly<{
1009
1126
  sha256(key: Buffer, data: Buffer): Buffer;
1010
1127
  verifySha256(key: Buffer, data: Buffer, expectedTag: Buffer): boolean;
@@ -1016,6 +1133,7 @@ declare const SignalisCore: Readonly<{
1016
1133
  OUTPUT_SIZE: 32;
1017
1134
  }>;
1018
1135
  secureRandom: typeof secureRandom;
1136
+ nativeSecureRandom: typeof nativeSecureRandom;
1019
1137
  randomNonce: typeof randomNonce;
1020
1138
  randomIv: typeof randomIv;
1021
1139
  randomKey: typeof randomKey;
@@ -1023,9 +1141,27 @@ declare const SignalisCore: Readonly<{
1023
1141
  fromHex: typeof fromHex;
1024
1142
  toBase64: typeof toBase64;
1025
1143
  fromBase64: typeof fromBase64;
1144
+ Base64: Readonly<{
1145
+ encode(input: Buffer): string;
1146
+ decode(input: string): Buffer;
1147
+ encodeUrlSafe(input: Buffer): string;
1148
+ decodeUrlSafe(input: string): Buffer;
1149
+ }>;
1150
+ Hex: Readonly<{
1151
+ encode(input: Buffer): string;
1152
+ encodeUpper(input: Buffer): string;
1153
+ decode(input: string): Buffer;
1154
+ isValid(input: string): boolean;
1155
+ }>;
1156
+ Utf8: Readonly<{
1157
+ encode(input: string): Buffer;
1158
+ decode(input: Buffer): string;
1159
+ isValid(input: Buffer): boolean;
1160
+ }>;
1026
1161
  constantTimeEqual: typeof constantTimeEqual;
1027
- VERSION: "0.2.0";
1162
+ constantTimeEq: typeof constantTimeEq;
1163
+ VERSION: "0.4.0";
1028
1164
  nativeVersion: string;
1029
1165
  }>;
1030
1166
 
1031
- export { AES_256_CBC_IV_SIZE, AES_256_GCM_NONCE_SIZE, AES_256_GCM_TAG_SIZE, AES_256_KEY_SIZE, AES_BLOCK_SIZE, AES_CBC, AES_GCM, AES_GCM_MAX_PLAINTEXT_SIZE, AES_GCM_RECOMMENDED_MESSAGES_PER_KEY, type AesCbcParams, type AesGcmParams, AuthenticationError, CHACHA20_POLY1305_KEY_SIZE, CHACHA20_POLY1305_NONCE_SIZE, CHACHA20_POLY1305_TAG_SIZE, CURVE25519_PRIVATE_KEY_SIZE, CURVE25519_PUBLIC_KEY_SIZE, CURVE25519_SHARED_SECRET_SIZE, ChaCha20Poly1305, CryptoError, Curve25519, ED25519_PRIVATE_KEY_SIZE, ED25519_PUBLIC_KEY_SIZE, ED25519_SEED_SIZE, ED25519_SIGNATURE_SIZE, Ed25519, type Encoding, HKDF, HKDF_MAX_OUTPUT_SIZE, HKDF_PRK_SIZE, HMAC, HMAC_SHA256_TAG_SIZE, type HkdfParams, KeyDerivationError, type KeyPair, LengthError, type PrivateKey, type PseudoRandomKey, type PublicKey, SHA256, SHA256_BLOCK_SIZE, SHA256_OUTPUT_SIZE, type SharedSecret, SignalisError, type Signature, SignatureError, VERSION, ValidationError, XED25519_PRIVATE_KEY_SIZE, XED25519_PUBLIC_KEY_SIZE, XED25519_RANDOM_SIZE, XED25519_SIGNATURE_SIZE, XEd25519, asPrivateKey, asPublicKey, asSharedSecret, asSignature, assertBuffer, assertBufferLength, assertBufferOfSize, assertHkdfLength, assertPositiveInteger, bufferToString, buffersSameLength, concat, constantTimeEq, constantTimeEqual, SignalisCore as default, fromBase64, fromBase64Url, fromHex, nativeSecureRandom, nativeVersion, randomIv, randomKey, randomNonce, secureRandom, stringToBuffer, toBase64, toBase64Url, toHex, xor, zeroize };
1167
+ export { AES_256_CBC_IV_SIZE, AES_256_GCM_NONCE_SIZE, AES_256_GCM_TAG_SIZE, AES_256_KEY_SIZE, AES_BLOCK_SIZE, AES_CBC, AES_GCM, AES_GCM_MAX_PLAINTEXT_SIZE, AES_GCM_RECOMMENDED_MESSAGES_PER_KEY, type AesCbcParams, type AesGcmParams, AuthenticationError, Base64, CHACHA20_POLY1305_KEY_SIZE, CHACHA20_POLY1305_NONCE_SIZE, CHACHA20_POLY1305_TAG_SIZE, CURVE25519_PRIVATE_KEY_SIZE, CURVE25519_PUBLIC_KEY_SIZE, CURVE25519_SHARED_SECRET_SIZE, ChaCha20Poly1305, CryptoError, Curve25519, ED25519_PRIVATE_KEY_SIZE, ED25519_PUBLIC_KEY_SIZE, ED25519_SEED_SIZE, ED25519_SIGNATURE_SIZE, Ed25519, type Encoding, HKDF, HKDF_MAX_OUTPUT_SIZE, HKDF_PRK_SIZE, HMAC, HMAC_SHA256_TAG_SIZE, Hex, type HkdfParams, KeyDerivationError, type KeyPair, LengthError, type PrivateKey, type PseudoRandomKey, type PublicKey, SHA256, SHA256_BLOCK_SIZE, SHA256_OUTPUT_SIZE, type SharedSecret, SignalisError, type Signature, SignatureError, Utf8, VERSION, ValidationError, XED25519_PRIVATE_KEY_SIZE, XED25519_PUBLIC_KEY_SIZE, XED25519_RANDOM_SIZE, XED25519_SIGNATURE_SIZE, XEd25519, asPrivateKey, asPublicKey, asSharedSecret, asSignature, assertBuffer, assertBufferLength, assertBufferOfSize, assertHkdfLength, assertPositiveInteger, bufferToString, buffersSameLength, concat, constantTimeEq, constantTimeEqual, SignalisCore as default, fromBase64, fromBase64Url, fromHex, nativeSecureRandom, nativeVersion, randomIv, randomKey, randomNonce, secureRandom, stringToBuffer, toBase64, toBase64Url, toHex, xor, zeroize };
package/dist/index.mjs CHANGED
@@ -725,6 +725,123 @@ function nativeSecureRandom(size) {
725
725
  }
726
726
  return native.secureRandom(size);
727
727
  }
728
+ var Base64 = Object.freeze({
729
+ /**
730
+ * Encode bytes to standard Base64 (with `=` padding).
731
+ */
732
+ encode(input) {
733
+ if (!Buffer.isBuffer(input)) {
734
+ throw new TypeError("Base64.encode: input must be a Buffer");
735
+ }
736
+ return native.base64Encode(input);
737
+ },
738
+ /**
739
+ * Decode a standard Base64 string back to bytes.
740
+ *
741
+ * @throws {RangeError} on invalid characters, wrong length, or invalid padding.
742
+ */
743
+ decode(input) {
744
+ if (typeof input !== "string") {
745
+ throw new TypeError("Base64.decode: input must be a string");
746
+ }
747
+ return native.base64Decode(input);
748
+ },
749
+ /**
750
+ * Encode bytes to URL-safe Base64 without padding.
751
+ * Uses `-` and `_` instead of `+` and `/`.
752
+ */
753
+ encodeUrlSafe(input) {
754
+ if (!Buffer.isBuffer(input)) {
755
+ throw new TypeError("Base64.encodeUrlSafe: input must be a Buffer");
756
+ }
757
+ return native.base64EncodeUrlSafe(input);
758
+ },
759
+ /**
760
+ * Decode a URL-safe Base64 string (no padding) back to bytes.
761
+ *
762
+ * @throws {RangeError} on invalid characters or wrong length.
763
+ */
764
+ decodeUrlSafe(input) {
765
+ if (typeof input !== "string") {
766
+ throw new TypeError("Base64.decodeUrlSafe: input must be a string");
767
+ }
768
+ return native.base64DecodeUrlSafe(input);
769
+ }
770
+ });
771
+ var Hex = Object.freeze({
772
+ /**
773
+ * Encode bytes to a lowercase hex string.
774
+ */
775
+ encode(input) {
776
+ if (!Buffer.isBuffer(input)) {
777
+ throw new TypeError("Hex.encode: input must be a Buffer");
778
+ }
779
+ return native.hexEncode(input);
780
+ },
781
+ /**
782
+ * Encode bytes to an uppercase hex string.
783
+ * (Rare, but included for legacy protocols.)
784
+ */
785
+ encodeUpper(input) {
786
+ if (!Buffer.isBuffer(input)) {
787
+ throw new TypeError("Hex.encodeUpper: input must be a Buffer");
788
+ }
789
+ return native.hexEncodeUpper(input);
790
+ },
791
+ /**
792
+ * Decode a hex string to bytes. Case-insensitive.
793
+ *
794
+ * @throws {RangeError} on odd-length input or non-hex characters.
795
+ */
796
+ decode(input) {
797
+ if (typeof input !== "string") {
798
+ throw new TypeError("Hex.decode: input must be a string");
799
+ }
800
+ return native.hexDecode(input);
801
+ },
802
+ /**
803
+ * Cheap validation: is this a well-formed hex string?
804
+ */
805
+ isValid(input) {
806
+ if (typeof input !== "string") {
807
+ throw new TypeError("Hex.isValid: input must be a string");
808
+ }
809
+ return native.hexIsValid(input);
810
+ }
811
+ });
812
+ var Utf8 = Object.freeze({
813
+ /**
814
+ * Encode a string to its UTF-8 byte representation.
815
+ */
816
+ encode(input) {
817
+ if (typeof input !== "string") {
818
+ throw new TypeError("Utf8.encode: input must be a string");
819
+ }
820
+ return native.utf8Encode(input);
821
+ },
822
+ /**
823
+ * Decode UTF-8 bytes to a string.
824
+ *
825
+ * @throws {RangeError} on invalid UTF-8 (truncated multi-byte, lone surrogate,
826
+ * invalid start byte, etc.). Unlike `Buffer.toString('utf-8')`, this does
827
+ * NOT silently substitute U+FFFD.
828
+ */
829
+ decode(input) {
830
+ if (!Buffer.isBuffer(input)) {
831
+ throw new TypeError("Utf8.decode: input must be a Buffer");
832
+ }
833
+ return native.utf8Decode(input);
834
+ },
835
+ /**
836
+ * Check whether the given bytes are valid UTF-8.
837
+ */
838
+ isValid(input) {
839
+ if (!Buffer.isBuffer(input)) {
840
+ throw new TypeError("Utf8.isValid: input must be a Buffer");
841
+ }
842
+ return native.utf8IsValid(input);
843
+ }
844
+ });
728
845
 
729
846
  // src/types.ts
730
847
  function asPublicKey(buf) {
@@ -812,7 +929,7 @@ function xor(a, b) {
812
929
  }
813
930
 
814
931
  // src/index.ts
815
- var VERSION = "0.2.0";
932
+ var VERSION = "0.4.0";
816
933
  var SignalisCore = Object.freeze({
817
934
  // Crypto primitives
818
935
  Curve25519,
@@ -821,22 +938,29 @@ var SignalisCore = Object.freeze({
821
938
  HKDF,
822
939
  AES_GCM,
823
940
  AES_CBC,
941
+ ChaCha20Poly1305,
824
942
  HMAC,
825
943
  SHA256,
826
944
  // Random
827
945
  secureRandom: secureRandom2,
946
+ nativeSecureRandom,
828
947
  randomNonce,
829
948
  randomIv,
830
949
  randomKey,
831
- // Encoding
950
+ // Encoding (JS-side legacy helpers — use Base64/Hex/Utf8 for native)
832
951
  toHex,
833
952
  fromHex,
834
953
  toBase64,
835
954
  fromBase64,
955
+ // Encoding (NEW v0.4.0 — native, RFC-compliant)
956
+ Base64,
957
+ Hex,
958
+ Utf8,
836
959
  // Security
837
960
  constantTimeEqual,
961
+ constantTimeEq: constantTimeEq2,
838
962
  // Version
839
- VERSION: "0.2.0",
963
+ VERSION,
840
964
  nativeVersion
841
965
  });
842
966
  var index_default = SignalisCore;
@@ -851,6 +975,7 @@ export {
851
975
  AES_GCM_MAX_PLAINTEXT_SIZE,
852
976
  AES_GCM_RECOMMENDED_MESSAGES_PER_KEY,
853
977
  AuthenticationError,
978
+ Base64,
854
979
  CHACHA20_POLY1305_KEY_SIZE,
855
980
  CHACHA20_POLY1305_NONCE_SIZE,
856
981
  CHACHA20_POLY1305_TAG_SIZE,
@@ -870,6 +995,7 @@ export {
870
995
  HKDF_PRK_SIZE,
871
996
  HMAC,
872
997
  HMAC_SHA256_TAG_SIZE,
998
+ Hex,
873
999
  KeyDerivationError,
874
1000
  LengthError,
875
1001
  SHA256,
@@ -877,6 +1003,7 @@ export {
877
1003
  SHA256_OUTPUT_SIZE,
878
1004
  SignalisError,
879
1005
  SignatureError,
1006
+ Utf8,
880
1007
  VERSION,
881
1008
  ValidationError,
882
1009
  XED25519_PRIVATE_KEY_SIZE,