@reallyme/crypto 0.3.9 → 0.3.11
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/README.md +10 -11
- package/dist/aead.js +1 -1
- package/dist/aesKw.js +1 -1
- package/dist/algorithms.js +1 -1
- package/dist/argon2id.js +1 -1
- package/dist/bip340Schnorr.js +1 -1
- package/dist/cryptoFacade.d.ts +60 -81
- package/dist/cryptoFacade.js +12 -408
- package/dist/cryptoFacadeAsymmetric.d.ts +20 -0
- package/dist/cryptoFacadeAsymmetric.js +252 -0
- package/dist/cryptoFacadeSymmetric.d.ts +27 -0
- package/dist/cryptoFacadeSymmetric.js +166 -0
- package/dist/digest.js +1 -1
- package/dist/ed25519.d.ts +2 -0
- package/dist/ed25519.js +45 -4
- package/dist/encodeEcdsaDer.js +1 -1
- package/dist/errors.js +1 -1
- package/dist/hkdf.js +1 -1
- package/dist/hmac.d.ts +3 -3
- package/dist/hmac.js +8 -5
- package/dist/hpke.d.ts +1 -1
- package/dist/hpke.js +4 -2
- package/dist/index.js +1 -1
- package/dist/jwaConcatKdf.js +1 -1
- package/dist/jwk.js +46 -11
- package/dist/kmac.js +1 -1
- package/dist/memory.js +1 -1
- package/dist/mlDsa.js +1 -1
- package/dist/mlKem.js +1 -1
- package/dist/operationResponse.js +1 -1
- package/dist/p256Ecdh.js +1 -1
- package/dist/p256Ecdsa.js +1 -1
- package/dist/p384Ecdh.js +1 -1
- package/dist/p384Ecdsa.js +1 -1
- package/dist/p521Ecdh.js +1 -1
- package/dist/p521Ecdsa.js +1 -1
- package/dist/pbkdf2.js +12 -4
- package/dist/proto/generated/reallyme/crypto/v1/crypto_pb.js +1 -1
- package/dist/proto.d.ts +8 -117
- package/dist/proto.js +6 -1085
- package/dist/protoAlgorithms.d.ts +21 -0
- package/dist/protoAlgorithms.js +323 -0
- package/dist/protoErrors.d.ts +27 -0
- package/dist/protoErrors.js +275 -0
- package/dist/protoIdentifiers.d.ts +14 -0
- package/dist/protoIdentifiers.js +112 -0
- package/dist/protoJwk.d.ts +10 -0
- package/dist/protoJwk.js +204 -0
- package/dist/protoValues.d.ts +63 -0
- package/dist/protoValues.js +228 -0
- package/dist/providerCatalog.js +1 -1
- package/dist/rsa.js +1 -1
- package/dist/secp256k1.js +1 -1
- package/dist/slhDsa.js +1 -1
- package/dist/validateBytes.js +1 -1
- package/dist/verifyBundledWasmModule.d.ts +63 -0
- package/dist/verifyBundledWasmModule.js +80 -0
- package/dist/wasm/reallyme_crypto_wasm.d.ts +383 -0
- package/dist/wasm/reallyme_crypto_wasm.js +8 -8
- package/dist/wasm/reallyme_crypto_wasm_bg.wasm +0 -0
- package/dist/wasmModuleTypes.js +1 -1
- package/dist/wasmProvider.d.ts +5 -0
- package/dist/wasmProvider.js +61 -3
- package/dist/x25519.js +1 -1
- package/dist/xWing.js +1 -1
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -42,9 +42,11 @@ Classical primitives are backed by pinned `@noble` packages. The primitives that
|
|
|
42
42
|
must stay identical to Rust — ML-KEM, ML-DSA, SLH-DSA, X-Wing, Argon2id, HPKE,
|
|
43
43
|
and others — are backed by a WASM module that ships prebuilt with the package.
|
|
44
44
|
|
|
45
|
-
Applications may
|
|
46
|
-
`ReallyMeCrypto` convenience API, or build isolated facade
|
|
47
|
-
|
|
45
|
+
Applications may install the package's initialized WASM module once for the
|
|
46
|
+
package-level `ReallyMeCrypto` convenience API, or build isolated facade
|
|
47
|
+
instances with `createReallyMeWasmProvider` and the same package-owned module.
|
|
48
|
+
Both paths reject replacement verification functions. Explicit facades reject
|
|
49
|
+
structural provider objects; missing or untrusted providers fail with
|
|
48
50
|
`provider-failure`. JWK/JWKS helpers delegate base64url and JCS canonicalization
|
|
49
51
|
to the published `@reallyme/codec` package, so applications that use those
|
|
50
52
|
helpers should also install the Codec WASM provider.
|
|
@@ -66,8 +68,8 @@ import {
|
|
|
66
68
|
} from "@reallyme/crypto";
|
|
67
69
|
import { initSync as initCryptoWasm } from "@reallyme/crypto/wasm/reallyme_crypto_wasm.js";
|
|
68
70
|
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
+
// Both the global installer and explicit facade bind to this package's
|
|
72
|
+
// initialized module namespace after verifying callable identity.
|
|
71
73
|
const wasmProvider: unknown = await import(
|
|
72
74
|
"@reallyme/crypto/wasm/reallyme_crypto_wasm.js"
|
|
73
75
|
);
|
|
@@ -94,15 +96,12 @@ const keyPair = ReallyMeCrypto.generateKemKeyPair("X-Wing-768");
|
|
|
94
96
|
const isolatedKeyPair = isolatedCrypto.generateKemKeyPair("X-Wing-768");
|
|
95
97
|
```
|
|
96
98
|
|
|
97
|
-
The explicit facade form is
|
|
98
|
-
applications because each instance owns its provider routing
|
|
99
|
-
|
|
99
|
+
The explicit facade form is useful for Workers, SSR, tests, and multi-bundle
|
|
100
|
+
applications because each instance owns its provider routing. The provider
|
|
101
|
+
must come from this package's initialized WASM module.
|
|
100
102
|
|
|
101
103
|
The package-owned WASM provider derives ML-DSA, ML-KEM, and X-Wing seed-based
|
|
102
104
|
keypairs inside Rust and returns the public key produced by that implementation.
|
|
103
|
-
Custom provider objects are trusted providers: if an application supplies its
|
|
104
|
-
own seed-derived keypair provider, it is responsible for public-key
|
|
105
|
-
correspondence and must be covered by its own conformance evidence.
|
|
106
105
|
|
|
107
106
|
## Raw WASM Module Contract
|
|
108
107
|
|
package/dist/aead.js
CHANGED
package/dist/aesKw.js
CHANGED
package/dist/algorithms.js
CHANGED
package/dist/argon2id.js
CHANGED
package/dist/bip340Schnorr.js
CHANGED
package/dist/cryptoFacade.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { ReallyMeAeadAlgorithm, ReallyMeHashAlgorithm, ReallyMeHkdfAlgorithm, ReallyMeHpkeSuite, ReallyMeJwaConcatKdfAlgorithm, ReallyMeKemAlgorithm, ReallyMeKeyAgreementAlgorithm, ReallyMeKeyWrapAlgorithm, ReallyMeKmacKdfAlgorithm, ReallyMeMacAlgorithm, ReallyMePbkdf2Algorithm, ReallyMeSignatureAlgorithm } from "./algorithms.js";
|
|
2
|
-
import type { ReallyMeRsaPublicKeyDerEncoding } from "./rsa.js";
|
|
3
1
|
import type { ReallyMeWasmProvider } from "./wasmProvider.js";
|
|
4
2
|
export type ReallyMeSignatureKeyPair = Readonly<{
|
|
5
3
|
publicKey: Uint8Array;
|
|
@@ -30,84 +28,65 @@ export type ReallyMeCryptoProviders = Readonly<{
|
|
|
30
28
|
* stable typed route and rejects algorithm/operation combinations that the
|
|
31
29
|
* selected method does not define.
|
|
32
30
|
*/
|
|
33
|
-
declare const createReallyMeCryptoFacade: (resolveWasmProvider: () => ReallyMeWasmProvider) => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
readonly deriveSharedSecret: (algorithm: ReallyMeKeyAgreementAlgorithm, publicKey: Uint8Array, secretKey: Uint8Array) => Uint8Array;
|
|
64
|
-
readonly deriveKeyAgreementKeyPair: (algorithm: ReallyMeKeyAgreementAlgorithm, secretKey: Uint8Array) => ReallyMeKeyAgreementKeyPair;
|
|
65
|
-
readonly generateKemKeyPair: (algorithm: ReallyMeKemAlgorithm) => ReallyMeKemKeyPair;
|
|
66
|
-
readonly deriveKemKeyPair: (algorithm: ReallyMeKemAlgorithm, secretKey: Uint8Array) => ReallyMeKemKeyPair;
|
|
67
|
-
readonly encapsulate: (algorithm: ReallyMeKemAlgorithm, publicKey: Uint8Array) => ReallyMeKemEncapsulation;
|
|
68
|
-
readonly decapsulate: (algorithm: ReallyMeKemAlgorithm, ciphertext: Uint8Array, secretKey: Uint8Array) => Uint8Array;
|
|
69
|
-
readonly sealHpke: (suite: ReallyMeHpkeSuite, recipientPublicKey: Uint8Array, info: Uint8Array, aad: Uint8Array, plaintext: Uint8Array) => ReallyMeHpkeSealedMessage;
|
|
70
|
-
readonly openHpke: (suite: ReallyMeHpkeSuite, recipientSecretKey: Uint8Array, encapsulatedKey: Uint8Array, info: Uint8Array, aad: Uint8Array, ciphertext: Uint8Array) => Uint8Array;
|
|
71
|
-
};
|
|
31
|
+
export declare const createReallyMeCryptoFacade: (resolveWasmProvider: () => ReallyMeWasmProvider) => Readonly<{
|
|
32
|
+
generateKeyPair(algorithm: import("./algorithms.js").ReallyMeSignatureAlgorithm): ReallyMeSignatureKeyPair;
|
|
33
|
+
deriveKeyPair(algorithm: import("./algorithms.js").ReallyMeSignatureAlgorithm, secretKey: Uint8Array): ReallyMeSignatureKeyPair;
|
|
34
|
+
sign(algorithm: import("./algorithms.js").ReallyMeSignatureAlgorithm, message: Uint8Array, secretKey: Uint8Array): Uint8Array;
|
|
35
|
+
signBip340Schnorr(message32: Uint8Array, secretKey: Uint8Array, auxRand32: Uint8Array): Uint8Array;
|
|
36
|
+
verify(algorithm: import("./algorithms.js").ReallyMeSignatureAlgorithm, signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): void;
|
|
37
|
+
verifyRsa(algorithm: import("./algorithms.js").ReallyMeSignatureAlgorithm, signature: Uint8Array, message: Uint8Array, publicKeyDer: Uint8Array, publicKeyEncoding: import("./rsa.js").ReallyMeRsaPublicKeyDerEncoding): void;
|
|
38
|
+
deriveSharedSecret(algorithm: import("./algorithms.js").ReallyMeKeyAgreementAlgorithm, publicKey: Uint8Array, secretKey: Uint8Array): Uint8Array;
|
|
39
|
+
deriveKeyAgreementKeyPair(algorithm: import("./algorithms.js").ReallyMeKeyAgreementAlgorithm, secretKey: Uint8Array): ReallyMeKeyAgreementKeyPair;
|
|
40
|
+
generateKemKeyPair(algorithm: import("./algorithms.js").ReallyMeKemAlgorithm): ReallyMeKemKeyPair;
|
|
41
|
+
deriveKemKeyPair(algorithm: import("./algorithms.js").ReallyMeKemAlgorithm, secretKey: Uint8Array): ReallyMeKemKeyPair;
|
|
42
|
+
encapsulate(algorithm: import("./algorithms.js").ReallyMeKemAlgorithm, publicKey: Uint8Array): ReallyMeKemEncapsulation;
|
|
43
|
+
decapsulate(algorithm: import("./algorithms.js").ReallyMeKemAlgorithm, ciphertext: Uint8Array, secretKey: Uint8Array): Uint8Array;
|
|
44
|
+
sealHpke(suite: import("./algorithms.js").ReallyMeHpkeSuite, recipientPublicKey: Uint8Array, info: Uint8Array, aad: Uint8Array, plaintext: Uint8Array): ReallyMeHpkeSealedMessage;
|
|
45
|
+
openHpke(suite: import("./algorithms.js").ReallyMeHpkeSuite, recipientSecretKey: Uint8Array, encapsulatedKey: Uint8Array, info: Uint8Array, aad: Uint8Array, ciphertext: Uint8Array): Uint8Array;
|
|
46
|
+
processOperationResponse(request: Uint8Array): Uint8Array;
|
|
47
|
+
processOperationResponseJson(requestJson: Uint8Array): Uint8Array;
|
|
48
|
+
hash(algorithm: import("./algorithms.js").ReallyMeHashAlgorithm, bytes: Uint8Array): Uint8Array;
|
|
49
|
+
seal(algorithm: import("./algorithms.js").ReallyMeAeadAlgorithm, key: Uint8Array, nonce: Uint8Array, aad: Uint8Array, plaintext: Uint8Array): Uint8Array;
|
|
50
|
+
open(algorithm: import("./algorithms.js").ReallyMeAeadAlgorithm, key: Uint8Array, nonce: Uint8Array, aad: Uint8Array, ciphertextWithTag: Uint8Array): Uint8Array;
|
|
51
|
+
authenticate(algorithm: import("./algorithms.js").ReallyMeMacAlgorithm, key: Uint8Array, message: Uint8Array): Uint8Array;
|
|
52
|
+
verifyMac(algorithm: import("./algorithms.js").ReallyMeMacAlgorithm, tag: Uint8Array, key: Uint8Array, message: Uint8Array): void;
|
|
53
|
+
deriveArgon2id(kdfVersion: number, secret: Uint8Array, salt: Uint8Array): Uint8Array;
|
|
54
|
+
deriveKey(algorithm: import("./algorithms.js").ReallyMePbkdf2Algorithm, password: Uint8Array, salt: Uint8Array, iterations: number, outputLength: number): Uint8Array;
|
|
55
|
+
deriveHkdf(algorithm: import("./algorithms.js").ReallyMeHkdfAlgorithm, inputKeyMaterial: Uint8Array, salt: Uint8Array, info: Uint8Array, outputLength: number): Uint8Array;
|
|
56
|
+
deriveJwaConcatKdfSha256(algorithm: import("./algorithms.js").ReallyMeJwaConcatKdfAlgorithm, sharedSecret: Uint8Array, algorithmId: Uint8Array, partyUInfo: Uint8Array, partyVInfo: Uint8Array, outputLength: number): Uint8Array;
|
|
57
|
+
deriveKmac256(algorithm: import("./algorithms.js").ReallyMeKmacKdfAlgorithm, key: Uint8Array, context: Uint8Array, customization: Uint8Array, outputLength: number): Uint8Array;
|
|
58
|
+
wrapKey(algorithm: import("./algorithms.js").ReallyMeKeyWrapAlgorithm, wrappingKey: Uint8Array, keyToWrap: Uint8Array): Uint8Array;
|
|
59
|
+
unwrapKey(algorithm: import("./algorithms.js").ReallyMeKeyWrapAlgorithm, wrappingKey: Uint8Array, wrappedKey: Uint8Array): Uint8Array;
|
|
60
|
+
}>;
|
|
72
61
|
export type ReallyMeCryptoFacade = ReturnType<typeof createReallyMeCryptoFacade>;
|
|
73
62
|
export declare const createReallyMeCrypto: (providers?: ReallyMeCryptoProviders) => ReallyMeCryptoFacade;
|
|
74
|
-
export declare const ReallyMeCrypto: {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
readonly deriveSharedSecret: (algorithm: ReallyMeKeyAgreementAlgorithm, publicKey: Uint8Array, secretKey: Uint8Array) => Uint8Array;
|
|
105
|
-
readonly deriveKeyAgreementKeyPair: (algorithm: ReallyMeKeyAgreementAlgorithm, secretKey: Uint8Array) => ReallyMeKeyAgreementKeyPair;
|
|
106
|
-
readonly generateKemKeyPair: (algorithm: ReallyMeKemAlgorithm) => ReallyMeKemKeyPair;
|
|
107
|
-
readonly deriveKemKeyPair: (algorithm: ReallyMeKemAlgorithm, secretKey: Uint8Array) => ReallyMeKemKeyPair;
|
|
108
|
-
readonly encapsulate: (algorithm: ReallyMeKemAlgorithm, publicKey: Uint8Array) => ReallyMeKemEncapsulation;
|
|
109
|
-
readonly decapsulate: (algorithm: ReallyMeKemAlgorithm, ciphertext: Uint8Array, secretKey: Uint8Array) => Uint8Array;
|
|
110
|
-
readonly sealHpke: (suite: ReallyMeHpkeSuite, recipientPublicKey: Uint8Array, info: Uint8Array, aad: Uint8Array, plaintext: Uint8Array) => ReallyMeHpkeSealedMessage;
|
|
111
|
-
readonly openHpke: (suite: ReallyMeHpkeSuite, recipientSecretKey: Uint8Array, encapsulatedKey: Uint8Array, info: Uint8Array, aad: Uint8Array, ciphertext: Uint8Array) => Uint8Array;
|
|
112
|
-
};
|
|
113
|
-
export {};
|
|
63
|
+
export declare const ReallyMeCrypto: Readonly<{
|
|
64
|
+
generateKeyPair(algorithm: import("./algorithms.js").ReallyMeSignatureAlgorithm): ReallyMeSignatureKeyPair;
|
|
65
|
+
deriveKeyPair(algorithm: import("./algorithms.js").ReallyMeSignatureAlgorithm, secretKey: Uint8Array): ReallyMeSignatureKeyPair;
|
|
66
|
+
sign(algorithm: import("./algorithms.js").ReallyMeSignatureAlgorithm, message: Uint8Array, secretKey: Uint8Array): Uint8Array;
|
|
67
|
+
signBip340Schnorr(message32: Uint8Array, secretKey: Uint8Array, auxRand32: Uint8Array): Uint8Array;
|
|
68
|
+
verify(algorithm: import("./algorithms.js").ReallyMeSignatureAlgorithm, signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): void;
|
|
69
|
+
verifyRsa(algorithm: import("./algorithms.js").ReallyMeSignatureAlgorithm, signature: Uint8Array, message: Uint8Array, publicKeyDer: Uint8Array, publicKeyEncoding: import("./rsa.js").ReallyMeRsaPublicKeyDerEncoding): void;
|
|
70
|
+
deriveSharedSecret(algorithm: import("./algorithms.js").ReallyMeKeyAgreementAlgorithm, publicKey: Uint8Array, secretKey: Uint8Array): Uint8Array;
|
|
71
|
+
deriveKeyAgreementKeyPair(algorithm: import("./algorithms.js").ReallyMeKeyAgreementAlgorithm, secretKey: Uint8Array): ReallyMeKeyAgreementKeyPair;
|
|
72
|
+
generateKemKeyPair(algorithm: import("./algorithms.js").ReallyMeKemAlgorithm): ReallyMeKemKeyPair;
|
|
73
|
+
deriveKemKeyPair(algorithm: import("./algorithms.js").ReallyMeKemAlgorithm, secretKey: Uint8Array): ReallyMeKemKeyPair;
|
|
74
|
+
encapsulate(algorithm: import("./algorithms.js").ReallyMeKemAlgorithm, publicKey: Uint8Array): ReallyMeKemEncapsulation;
|
|
75
|
+
decapsulate(algorithm: import("./algorithms.js").ReallyMeKemAlgorithm, ciphertext: Uint8Array, secretKey: Uint8Array): Uint8Array;
|
|
76
|
+
sealHpke(suite: import("./algorithms.js").ReallyMeHpkeSuite, recipientPublicKey: Uint8Array, info: Uint8Array, aad: Uint8Array, plaintext: Uint8Array): ReallyMeHpkeSealedMessage;
|
|
77
|
+
openHpke(suite: import("./algorithms.js").ReallyMeHpkeSuite, recipientSecretKey: Uint8Array, encapsulatedKey: Uint8Array, info: Uint8Array, aad: Uint8Array, ciphertext: Uint8Array): Uint8Array;
|
|
78
|
+
processOperationResponse(request: Uint8Array): Uint8Array;
|
|
79
|
+
processOperationResponseJson(requestJson: Uint8Array): Uint8Array;
|
|
80
|
+
hash(algorithm: import("./algorithms.js").ReallyMeHashAlgorithm, bytes: Uint8Array): Uint8Array;
|
|
81
|
+
seal(algorithm: import("./algorithms.js").ReallyMeAeadAlgorithm, key: Uint8Array, nonce: Uint8Array, aad: Uint8Array, plaintext: Uint8Array): Uint8Array;
|
|
82
|
+
open(algorithm: import("./algorithms.js").ReallyMeAeadAlgorithm, key: Uint8Array, nonce: Uint8Array, aad: Uint8Array, ciphertextWithTag: Uint8Array): Uint8Array;
|
|
83
|
+
authenticate(algorithm: import("./algorithms.js").ReallyMeMacAlgorithm, key: Uint8Array, message: Uint8Array): Uint8Array;
|
|
84
|
+
verifyMac(algorithm: import("./algorithms.js").ReallyMeMacAlgorithm, tag: Uint8Array, key: Uint8Array, message: Uint8Array): void;
|
|
85
|
+
deriveArgon2id(kdfVersion: number, secret: Uint8Array, salt: Uint8Array): Uint8Array;
|
|
86
|
+
deriveKey(algorithm: import("./algorithms.js").ReallyMePbkdf2Algorithm, password: Uint8Array, salt: Uint8Array, iterations: number, outputLength: number): Uint8Array;
|
|
87
|
+
deriveHkdf(algorithm: import("./algorithms.js").ReallyMeHkdfAlgorithm, inputKeyMaterial: Uint8Array, salt: Uint8Array, info: Uint8Array, outputLength: number): Uint8Array;
|
|
88
|
+
deriveJwaConcatKdfSha256(algorithm: import("./algorithms.js").ReallyMeJwaConcatKdfAlgorithm, sharedSecret: Uint8Array, algorithmId: Uint8Array, partyUInfo: Uint8Array, partyVInfo: Uint8Array, outputLength: number): Uint8Array;
|
|
89
|
+
deriveKmac256(algorithm: import("./algorithms.js").ReallyMeKmacKdfAlgorithm, key: Uint8Array, context: Uint8Array, customization: Uint8Array, outputLength: number): Uint8Array;
|
|
90
|
+
wrapKey(algorithm: import("./algorithms.js").ReallyMeKeyWrapAlgorithm, wrappingKey: Uint8Array, keyToWrap: Uint8Array): Uint8Array;
|
|
91
|
+
unwrapKey(algorithm: import("./algorithms.js").ReallyMeKeyWrapAlgorithm, wrappingKey: Uint8Array, wrappedKey: Uint8Array): Uint8Array;
|
|
92
|
+
}>;
|