| Summary || Products || Cryptography || Fusion || KeeeX.Js || Verifier || KeeeX Chain || Digital Identity Management |
| Description || Quickstart |
KeeeX Fusion is our core tool.
It handles input files and outputs keeexed files, embedding various metadata into them.
It is a tool that runs on customers' servers and can scale horizontally as needed.
It provides multiple interfaces and ways of deployment to accommodate various industrial use cases.
Processing a single file follows this general workflow:
This diagram illustrates the process of using the KeeeX Fusion service to transform a raw input file into a keeexed file, incorporating both automatically generated metadata and user-defined metadata.
The IDX represents the unique identifier generated by the Fusion service, which is then timestamped using the KeeeX API.
The actual process typically includes an additional step for digital signature, not shown in the diagram for simplicity's sake.
The handling of digital signatures is described in a later section on this page.
KeeeX Fusion does not require a lot of resources to operate.
It is available for most modern Linux and Windows-based operating systems running on the common x86-64 architecture, and can be made available for other OSes provided they also support Node JS.
The memory footprint of the software itself with its standard distribution is approximately 150MB.
Additional memory usage depends on the size of the processed files.
CPU usage is minimal.
Minimal requirements:
We provide the tool in two main forms:
On demand, it's also possible to gain access to a JavaScript library for dedicated use cases; however, this is not covered in this documentation.
Distribution of the standalone executable is done either through our file sharing service or via a Debian-based repository (.deb package).
Distribution of the Docker image is done through a private Docker registry.
Embedding Fusion on client devices requires additional work and a server to provide service authorization.
Depending on which distribution channel you obtain Fusion from, it can operate in two different modes:
Note that the server daemon heavily relies on the data structure used by the CLI, so it's advised to read both sections.
For regular operations, KeeeX Fusion requires some initial configuration.
Performing a verification and general offline operations do not require any configuration, but keeexing files and performing timestamps require at least a valid and active KeeeX user account.
The simplest way to specify KeeeX Fusion's configuration is by using a JSON file:
{
"user": "<valid keeex login>",
"password": "<associated password>"
}
In addition to credentials, you can also specify the following optional parameters:
localCache: set to true to locally store authentication information to speed up the starting process on subsequent calls.localCacheFile: if localCache is enabled, allows specifying a custom file path for the cached information.proxy: if the network does not provide internet connectivity, specify a proxy that will be used to reach KeeeX's services.The proxy configuration is in the following format:
{
"proxy": {
"url": "https://someproxy.invalid:1234",
"credentials": {
"login": "somelogin",
"password": "somepassword"
}
}
}
It supports both HTTP/HTTPS proxies and SOCKS proxies.
The configuration can also be specified using environment variables, which can be useful for deployment in a containerized environment.
Refer to the full documentation for an exhaustive list of configuration entries and their corresponding environment variables.
When running KeeeX Fusion as a standalone CLI application, it can perform a set of predefined actions:
keeex to keeex a file, embedding metadata in itverify to validate the content of a file and extract its associated metadatasign to inject digital signatures into a pre-keeexed filestatus to perform some self-diagnostic routines to identify issuesThis list is not exhaustive; more advanced features are available.
Likewise, all actions described below are intended to provide an easy-to-understand, quick-start guide.
For more advanced usage, please refer to the full documentation.
The CLI interface always uses the following syntax:
fusion [-c <configuration file>] -a <action> -d <JSON argument>
To keeex a file, you need to provide both the input and output paths, as well as metadata and options to use.
The most basic example to produce a keeexed file with no extra metadata or options is:
{
"src": "input.txt",
"dst": "output.txt",
}
Using this JSON argument will result in a keeexed file with an IDX and system time embedded in it, but no digital signature or timestamp.
While there are use cases where this might be enough, it's recommended to use at least a digital signature to ensure the integrity of the keeexed file.
A more realistic example would be:
{
"src": "input.txt",
"dst": "output.txt",
"mdata": {
"identities": [
{
"type": "bitcoin",
"wif": "Ky9wu9jNbxJgvreN4aBa22hrMJLB6wt7kj1MMSru8wzeKmeMrEcN"
}
],
"properties": {
"file_purpose": "sample file"
}
},
"options": {
"timestamp": true
}
}
This example will keeex the file, embed a digital signature with the signatory's address "1QK4C1Jbuqtd8rsB2ZDWz1k7fmgxLopAfz" (using a Bitcoin-message signature), and timestamp the produced IDX.
It will also embed a custom property named file_purpose whose value is sample file.
Running the command will output something similar to the following:
{
"mainIdx": "xohak-hofar-tegik-sanom-razuh-devur-sovul-talet-huveb-razov-libuv-cicoh-pykec-ticyg-nicak-pepuc-goxyx",
"timestamp": {
"anchors": [],
"idx": "xohak-hofar-tegik-sanom-razuh-devur-sovul-talet-huveb-razov-libuv-cicoh-pykec-ticyg-nicak-pepuc-goxyx",
"timestampRequestDate": "2024-12-19T14:42:38.976Z"
}
}
The output file's IDX is available, along with feedback from KeeeX's services regarding the timestamp request.
From now on, the output file can be referred to by its IDX, and any service or user looking at the file can confirm that it was not changed by checking this IDX.
There are multiple other metadata types that can be embedded; here's a non-exhaustive list:
These types of embedded metadata are normalized to provide a consistent way to query content with all our tooling.
The options property allows some customization in the way the file is processed, such as enabling/disabling timestamping (as demonstrated). It also allows you to specify some level of optimizations for corner cases, alter the embedding method, etc.
The action of verifying a file means the following operations:
The JSON argument to perform a verify operation is as follows:
{
"src": "output.txt",
"onlineInfo": true,
}
Running the verify command on a file that was keeexed using the above command will output the following information:
{
"identities": [
{
"address": "1QK4C1Jbuqtd8rsB2ZDWz1k7fmgxLopAfz",
"keyAddress": "1QK4C1Jbuqtd8rsB2ZDWz1k7fmgxLopAfz",
"optional": false,
"signable": "2024-12-19T14:42:38.904Z|xohak-hofar-tegik-sanom-razuh-devur-sovul-talet-huveb-razov-libuv-cicoh-pykec-ticyg-nicak-pepuc-goxyx",
"signature": "IL8+SO+8kEPbCQ8o6DyC4Qpr+OjXUyGA5+MMd5ivEWDBttJoj30GXNtivRTs4xPUAsizUH0zSA7BIM273hSnyxs=",
"status": "VALID",
"topicId": 0,
"type": "bitcoin",
"timestamp": "2024-12-19T14:42:38.904Z"
}
],
"idxs": [
{
"algorithm": "sha3-256+sha256",
"encoding": "bubble-babble",
"main": true,
"recursive": false,
"value": "xohak-hofar-tegik-sanom-razuh-devur-sovul-talet-huveb-razov-libuv-cicoh-pykec-ticyg-nicak-pepuc-goxyx"
},
{
"algorithm": "sha256",
"encoding": "hex",
"main": false,
"recursive": true,
"value": "b40c7eb820a07811a2718534d1f4e86567230bc1782b0bf7af64171ff75197c3"
}
],
"license": {
"licenseDate": "2024-12-19T14:42:38.150Z",
"licenseMode": "online",
"licenseText": "Protected By KeeeX",
"userIdx": "ximav-kerim-levym-mihyk-fagok-kokod-pykar-zobol-mydic-cepoc-hecym-sopap-fovib-hesyg-zomyv-kynic-taxex"
},
"mainIdx": "xohak-hofar-tegik-sanom-razuh-devur-sovul-talet-huveb-razov-libuv-cicoh-pykec-ticyg-nicak-pepuc-goxyx",
"name": "",
"properties": {
"kx.description": {
"value": ""
},
"kx.author": {
"value": ""
},
"file_purpose": {
"value": "sample file"
},
"kx.afterbc": {
"value": "BC|ETH.main|21437234|d9c676b77f9f728655f513be390be3631de71fa976826624dd3cdf1dac5c35ae|2024-12-19T14:42:38.575Z"
},
"kx.time": {
"value": "2024-12-19T14:42:38.726Z"
}
},
"statementVersion": "2",
"status": "VALID",
"target": "prod",
"appVersion": "@keeex/js-fusion@7.1.2",
"time": "2024-12-19T14:42:38.726Z",
"afterBc": {
"date": "2024-12-19T14:42:38.575Z",
"text": "Block #21437234 from Ethereum at 2024-12-19T14:42:38.575Z: d9c676b77f9f728655f513be390be3631de71fa976826624dd3cdf1dac5c35ae",
"checkUrl": "https://live.blockcypher.com/eth/block/d9c676b77f9f728655f513be390be3631de71fa976826624dd3cdf1dac5c35ae/",
"height": 21437234,
"blockchainName": "Ethereum",
"hash": "d9c676b77f9f728655f513be390be3631de71fa976826624dd3cdf1dac5c35ae"
},
"timestampInfo": {
"anchors": [
{
"certificate": "keeex_tsa_certificate_2024.cer",
"idxAsMessage": true,
"ignoreCritical": false,
"timestamp": "2024-12-19T14:42:38.979Z",
"tsrUrl": "https://services.keeex.me/timestamps/tsa/xohak-hofar-tegik-sanom-razuh-devur-sovul-talet-huveb-razov-libuv-cicoh-pykec-ticyg-nicak-pepuc-goxyx.tsr",
"type": "rfc3161Keeex"
},
{
"timestamp": "2024-12-19T14:42:38.986Z",
"transactionHash": "0x407419b788bb9623413636b481cc130ba0d1384b0c21369c37d4c76cad281b45",
"type": "ethereumKeeex"
}
],
"idx": "xohak-hofar-tegik-sanom-razuh-devur-sovul-talet-huveb-razov-libuv-cicoh-pykec-ticyg-nicak-pepuc-goxyx",
"timestampRequestDate": "2024-12-19T14:42:38.976Z"
}
}
This is actually the full output of the command.
While it may look complex, it is split into separate sections.
The most important parts are the mainIdx, which identifies the document and must match an expected value when comparing documents, and the status field, which should be VALID.
As long as the status is indicated as VALID, the rest of the metadata can be trusted to not have been altered, and the digital signatures are valid.
This documentation will not go into extensive details about all reported information, but you can find custom properties set when keeping the file, signatory information, timestamp information, and so on.
If there is any mismatch, or if the trust level of the data cannot be confirmed because it lacks a digital signature, it will be reported in the same output with details.
The status action does not take any JSON argument, and will output a JSON report of various checks to ensure that KeeeX Fusion can operate as expected.
It is useful for debugging issues with the configuration, the KeeeX account used, the network, or the execution environment.
Here is a typical output when everything is working correctly:
{
"apiStatus": {
"reachable": true,
"reachableWithoutProxy": true
},
"configStatus": {
"config": {
"defaultIdentity": {
"always": false,
"key": {
"address": "<undefined>",
"passphrase": "<undefined>",
"type": "bitcoin",
"wif": "string(52)"
},
"role": "<redacted for the wiki>"
},
"license": "<undefined>",
"password": "string(20)",
"proxy": "<undefined>",
"user": "<redacted for the wiki>"
},
"haveCredentials": true,
"haveDefaultIdentity": true,
"haveProxy": false
},
"credentialsStatus": {
"allowedTimestampMethods": [
{
"type": "rfc3161Keeex"
},
{
"type": "bitcoin"
},
{
"type": "ethereumKeeex"
}
],
"canKeeex": true,
"canTimestamp": true,
"defaultTimestampMethods": [
"rfc3161Keeex",
"bitcoin",
"ethereumKeeex"
],
"validCredentials": true
},
"issues": [],
"licenseStatus": "<undefined>",
"status": "ok",
"version": {
"current": "7.1.2",
"latest": "<undefined>"
}
}
Typically, a value other than ok in the status property would indicate an issue, and any detected issues (errors or warnings) would be listed in the issues property.
The KeeeX Fusion tool can be run in daemon mode, which exposes an interface for running multiple actions in sequence.
In contrast to regular CLI usage, this provides several advantages when processing a large number of files:
While there are multiple options for interfacing with the daemon service, the most convenient one is the HTTP interface.
This documentation will focus on it.
Starting the daemon service is accomplished by running the daemon action.
fusion [-c <configuration file>] -a daemon -d '{"mode":"http"}'
Upon running this command, the daemon displays the following:
[O| 3693] {"pid":332058,"port":41455,"spinupTime":3.7,"status":"ready"}
It will then continue to log every action in a similar fashion.
There are a few additional options that can be passed to the daemon action:
port: a number indicating which port to listen on. If not provided, a random available port will be used and reported in the first logged output.tempDirectory: a directory for placing temporary files when they are received by the HTTP interfacebindAddress: an address to bind the listening service on (other than "127.0.0.1")threads: a parameter for controlling the number of threads; it defaults to the number of available logical cores.Note that this HTTP daemon does not implement TLS or any authentication mechanism.
It is designed to be run in a secure environment, likely a containerized one, or at the very least with no public access.
While it may be possible to run it behind a reverse proxy, care must be taken to implement some level of authentication.
The expected use case is deployment in a fully controlled infrastructure as part of a larger system.
Sending requests to the HTTP daemon can be done in two ways: either by providing a JSON body or using a multipart/form-data encoding to also send a file.
The routes are basically http://127.0.0.1:<port>/<action> and all calls use the "POST" HTTP method.
For example, running the KeeeX Fusion tool in daemon mode and sending the JSON argument from above to the http://localhost:41455/keeex endpoint would have the exact same effect as running the command-line tool.
While it is possible to provide the src and dst arguments as with the CLI, this requires the files to be accessible through the system's file system, which is not always the case, especially with containerized HTTP services.
If the files need to be sent or retrieved from another source, it is mandatory to use multipart/form-data encoding to transmit the request.
The JSON argument must be sent as the data field of the form data.
To send a file as the src property, you must provide src with the value "-" and provide the file content as a file field in the form data.
To receive the output of the action in the request's reply, set the dst value to "-".
In that case, the output will be the body of the reply, and the command's output will be put in the custom HTTP header X-KeeeX-Result (usually used to retrieve the keeexed file's IDX).
Note that you can mix using "-" for src and dst in the same request, and you can also use regular paths.
A typical example would be an archival solution, where the input file is received with the HTTP request, and the output is written on a mounted storage inside the container or where the service is executed.
In that case, the dst property could simply be a local file path.
Digital signatures are essential for ensuring the authenticity of a file.
Their primary use is to verify that the file has originated from either a trusted server or has been validated by a trusted user.
The digital signatures used in KeeeX Fusion, as well as in most large-scale applications nowadays, are based on public-key cryptography.
These signatures are produced using a key pair, consisting of a public part and a private part.
While we won't delve into the mathematics behind them, digital signatures have the following properties:
As such, the private key must be kept secret, and the public key can be shared with anyone.
A proper digital signature mechanism that involves an end-user must take into account that the private keys are never to be divulged to anyone except their owner.
Effectively, anyone with access to the private key can produce digital signatures that would be validated against the associated public key.
In addition to the basics of having a private and public key, you will find throughout KeeeX documentation references to what we call a "key address".
These addresses are derived from the public key and are used in certain environments.
In our case, it originated from using Bitcoin's message feature, where signatures are associated with an address that represents a key pair along with extra information about the network.
We have extended this concept to be able to use a simple string to distinguish between multiple types of public keys used in different environments.
The gist of it is that an address can be derived from a public key; an address can be used to validate a digital signature, but it is impossible to derive the public key from an address.
To ensure the authenticity of a file, KeeeX embeds digital signatures into keeexed files.
These digital signatures must be produced using a key pair, including a private key, for at least one signatory.
It is possible to embed multiple digital signatures with different "roles" in a single file, such as having both a service-specific digital signature and the end-user's signature.
However, this raises several concerns:
The first point, determining what constitutes a trusted signatory, is solution-dependent.
There are standards and tools used to associate a digital identity with a cryptographic key pair.
Compatibility with such systems, as well as some KeeeX-provided solutions, is described in the Digital Identity Management page.
Ultimately, KeeeX Fusion can validate that signatures match the expected signatories, but it cannot verify the actual digital identity behind those signatories.
It is up to the caller or service to determine what constitutes a trusted signatory.
The second point, producing signatures, is handled in two ways as far as KeeeX Fusion is concerned.
The first option is to actually provide the private key to KeeeX Fusion.
This is done through the identities metadata, and is illustrated above.
When Fusion keeexes a file, it uses all provided identities to create signature placeholders.
When such a placeholder is made from a private key, the signature is automatically calculated and inserted.
This is useful for server-side authentication of data, ensuring that it was processed by a given service, for example.
The second option is to provide only the key address to KeeeX Fusion.
In this case, as described above, a suitable placeholder will be prepared in the file, but the signature will not be injected (since it is not yet available).
The signature is expected to be computed by a third party through other tools, including KeeeX.Js.
At a later date, the sign action can be used on an already keeexed file to inject a signature into an existing placeholder.
Doing so will not change the file's IDX, as the signature is not part of the keeexed content.
For the example below, we will use a random Bitcoin key.
Its WIF (the equivalent of the private key part) is Ky9wu9jNbxJgvreN4aBa22hrMJLB6wt7kj1MMSru8wzeKmeMrEcN.
Its address is 1QK4C1Jbuqtd8rsB2ZDWz1k7fmgxLopAfz.
The general workflow is as follows (each step can be run on different systems):
Keeexing the file with a placeholder signature:
$ fusion -a keeex -d '{ \
"src": "input.txt", \
"dst": "output.txt", \
"mdata": {"identities": [{"type": "bitcoin", "address": "1QK4C1Jbuqtd8rsB2ZDWz1k7fmgxLopAfz"}]}
}'
{
"mainIdx": "xutar-zusid-lolir-bogup-dibet-kumab-makef-beveh-zepat-nisek-mirug-hofut-ducim-povyn-sezam-nupuf-foxax"
}
Obtaining the signable details:
$ fusion -a verify -d '{"src": "output.txt"}'
{
"identities": [
{
"address": "1QK4C1Jbuqtd8rsB2ZDWz1k7fmgxLopAfz",
"keyAddress": "1QK4C1Jbuqtd8rsB2ZDWz1k7fmgxLopAfz",
"optional": false,
"signable": "2024-12-19T16:27:27.285Z|xutar-zusid-lolir-bogup-dibet-kumab-makef-beveh-zepat-nisek-mirug-hofut-ducim-povyn-sezam-nupuf-foxax",
"signature": "cGxhY2Vob2xkZXJwbGFjZWhvbGRlcnBsYWNlaG9sZDFRSzRDMUpidXF0ZDhyc0IyWkRXejFrN2ZtZ3hMb3BBZno=",
"status": "MISSING",
"topicId": 0,
"type": "bitcoin",
"timestamp": "2024-12-19T16:27:27.285Z"
}
],
"mainIdx": "xutar-zusid-lolir-bogup-dibet-kumab-makef-beveh-zepat-nisek-mirug-hofut-ducim-povyn-sezam-nupuf-foxax",
"status": "MISSINGSIGNATURES",
// … other fields …
}
The output of the verify action on a file with missing signatures has a different status (MISSING_SIGNATURES) and the identities array contains an identity with a status of MISSING.
The signable field in the identity object contains the string that needs to be signed, along with the timestamp that is "now" at the time the command is run.
Producing said signature can be done using multiple tools, including KeeeX Fusion itself.
It would usually be done client-side, in a mobile application or in a web page, using other tools such as KeeeX.Js.
For this example, we will use KeeeX Fusion.
$ fusion -a computeSignature -d '{ \
"identity": {"type": "bitcoin", "wif": "Ky9wu9jNbxJgvreN4aBa22hrMJLB6wt7kj1MMSru8wzeKmeMrEcN"}, \
"data": "2024-12-19T16:27:27.285Z|xutar-zusid-lolir-bogup-dibet-kumab-makef-beveh-zepat-nisek-mirug-hofut-ducim-povyn-sezam-nupuf-foxax" \
}'
{
"address": "1QK4C1Jbuqtd8rsB2ZDWz1k7fmgxLopAfz",
"data": "2024-12-19T16:27:27.285Z|xutar-zusid-lolir-bogup-dibet-kumab-makef-beveh-zepat-nisek-mirug-hofut-ducim-povyn-sezam-nupuf-foxax",
"signature": "IOR1leJv6bvRTnM+U7FeSrr2rWmO+TkA3gm8VeqLMpIDcaGNc55eDEmFvAi3bfD986pROH2ZkPHzicL2XYO7VhE="
}
This signature could have been obtained using any tool that can handle legacy Bitcoin message signatures.
Embedding this signature in the file is done using the sign action:
$ fusion -a sign -d '{ \
"src":"output.txt", \
"dst":"output.txt", \
"signatures":[{ \
"type": "bitcoin", \
"address":"1QK4C1Jbuqtd8rsB2ZDWz1k7fmgxLopAfz", \
"signature":"IOR1leJv6bvRTnM+U7FeSrr2rWmO+TkA3gm8VeqLMpIDcaGNc55eDEmFvAi3bfD986pROH2ZkPHzicL2XYO7VhE=", \
"timestamp":"2024-12-19T16:27:27.285Z" \
}] \
}'
{/* … verify file output … */}
Note that the timestamp provided must match the one used in the signable value from before.
It is also possible to output to a different file by changing the dst field.
After this, the file is fully keeexed, and its status will be VALID, indicating that all expected signatures are present and valid.
Combining this workflow with client-side generation of signatures and proper private key management allows for a secure way for users to sign data without disclosing their private keys to the service.
Adding a service or infrastructure that matches users to their public keys, it becomes possible to authenticate data and digital signatures with complete trust in the system, including the trust that the service itself is not in any position to forge end-user digital signatures.
The old supported version of KeeeX Fusion is called "KeeeX Fusion" and is on version 1.3.0.
This version is replaced by a new version called "KeeeX Fusion 2".
The old version will remain available for a transition period but is not recommended for new projects.
Migration from the old version to the new is expected to be smooth; an accompanying documentation is provided, and most changes related to previously existing features will require at most some minor property renaming.
Note that keeexed files, regardless of which version of our tools was used to create them, always remain compatible with later versions.
| Product version | Software version | Availability date | State | Statement version | Note |
|---|---|---|---|---|---|
| Fusion1 | 1.3.0 | September 2022 | Old, still supported | 1 | CLI only |
| Fusion2 | 5.3 | November 2022 | Beta, unsupported | 1 | CLI + Server |
| Fusion2 | 6.2 | May 2024 | Beta, unsupported | 2 | CLI + Server |
| Fusion2 | 7.1 | August 2024 | Beta, unsupported | 2 | CLI + Server |
| Fusion2 | 7.5+ | February 2026 | Current | 2 | CLI + Server |
New users have to start by using the latest version; it is not possible to obtain license files for the old version anymore.
Note: We use semantic versioning, meaning that our software versions are comprised of three numbers:
New features are never added in "patch" versions, so it is enough to refer to the "major" and "minor" version numbers when considering compatibility.