mirror of
https://github.com/cryptpad/cryptpad.git
synced 2026-09-12 19:49:59 +05:00
Merge branch '2025.3.1-rc' into moderation
This commit is contained in:
commit
aba6a16cd8
5
.github/ISSUE_TEMPLATE/bug_resolution.yml
vendored
5
.github/ISSUE_TEMPLATE/bug_resolution.yml
vendored
@ -89,13 +89,10 @@ body:
|
||||
label: Version
|
||||
description: What version of CryptPad are you running?
|
||||
options:
|
||||
- 2025.3.0
|
||||
- 2024.12.0
|
||||
- 2024.9.1
|
||||
- 2024.9.0
|
||||
- 2024.6.1
|
||||
- 2024.6.0
|
||||
- 2024.3.1
|
||||
- 2024.3.0
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@ -4,6 +4,11 @@ SPDX-FileCopyrightText: 2023 XWiki CryptPad Team <contact@cryptpad.org> and cont
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
# Release (2025.3.1)
|
||||
|
||||
> [!NOTE]
|
||||
> The new version of OnlyOffice is much bigger than the previous versions. When installing version 8.3 with `install-onlyoffice.sh` ~830MB additional disk space is needed.
|
||||
|
||||
# 💐 Spring 2025 release (2025.3.0)
|
||||
|
||||
## Goals
|
||||
|
||||
@ -1,10 +0,0 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
@ -22,4 +22,5 @@ We do also communicate about this topic on:
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Vulnerabilities can be reported using the GitHub Security interface. You can also send us an email at security@cryptpad.org
|
||||
Brefore reaching out about a potential vulnerability, ensure it falls within the scope of our project. Please read thoroughly our [whitepaper](https://blog.cryptpad.org/2023/02/02/Whitepaper/) describing our threat model and what we consider acceptable or not security-wise. If you are sure you found a real vulnerability, you can report it using the GitHub Security interface. You can also send us an email at security@cryptpad.org
|
||||
|
||||
|
||||
@ -53,8 +53,8 @@ define([
|
||||
var keys = Nacl.sign.keyPair();
|
||||
var inviteToken = window.location.hash.slice(1);
|
||||
localStorage.CP_sso_auth = JSON.stringify({
|
||||
s: Nacl.util.encodeBase64(keys.secretKey),
|
||||
p: Nacl.util.encodeBase64(keys.publicKey),
|
||||
s: Util.encodeBase64(keys.secretKey),
|
||||
p: Util.encodeBase64(keys.publicKey),
|
||||
token: inviteToken
|
||||
});
|
||||
ServerCommand(keys, {
|
||||
|
||||
@ -137,6 +137,13 @@ define(req, function(AppConfig, Default, Language) {
|
||||
Messages.admin_documentsDeletionHint = "Archive a list of documents using their id (one document id per line)";
|
||||
Messages.admin_documentsDeletionTitle = "Archive multiple documents";
|
||||
|
||||
// XXX
|
||||
Messages.badges_admin = "Instance administrator";
|
||||
Messages.badges_moderator = "Instance moderator";
|
||||
Messages.badges_premium = "Premium user";
|
||||
Messages.badges_error = "Error while validating this user's data";
|
||||
Messages.profile_badges = "Badges";
|
||||
|
||||
return Messages;
|
||||
|
||||
});
|
||||
|
||||
34
customize.dist/src/less2/include/badges.less
Normal file
34
customize.dist/src/less2/include/badges.less
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 XWiki CryptPad Team <contact@cryptpad.org> and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
@import (reference) "./colortheme-all.less";
|
||||
@import (reference) "./variables.less";
|
||||
.badges_vars(
|
||||
@width: 30px
|
||||
) {
|
||||
@badges-width: @width;
|
||||
}
|
||||
.badges_main(@width: 30px) {
|
||||
--LessLoader_require: LessLoader_currentFile();
|
||||
.badges_vars(@width);
|
||||
--badges-width: @badges-width;
|
||||
--badges-font: ceil(@badges-width*2/3);
|
||||
}
|
||||
& {
|
||||
.badges_vars();
|
||||
i.cp-badge {
|
||||
width: var(--badges-width);
|
||||
height: var(--badges-width);
|
||||
box-sizing: border-box;
|
||||
border: 1px solid @cryptpad_text_col;
|
||||
border-radius: 50%;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: var(--badges-font);
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,6 +263,14 @@
|
||||
.cp-toolbar-userlist-friend {
|
||||
padding: 0;
|
||||
}
|
||||
.cp-userlist-badge {
|
||||
i {
|
||||
color: @cryptpad_color_brand;
|
||||
}
|
||||
i.cp-badge-error {
|
||||
color: @cryptpad_color_warn_red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,6 +104,7 @@ server {
|
||||
# Enable SharedArrayBuffer in Firefox (for .xlsx export)
|
||||
add_header Cross-Origin-Resource-Policy cross-origin;
|
||||
add_header Cross-Origin-Embedder-Policy require-corp;
|
||||
add_header Referrer-Policy same-origin;
|
||||
|
||||
# Insert the path to your CryptPad repository root here
|
||||
root /home/cryptpad/cryptpad;
|
||||
@ -169,6 +170,7 @@ server {
|
||||
# they unfortunately still require exceptions to the sandboxing to work correctly.
|
||||
if ($uri ~ ^/(?:sheet|doc|presentation)/inner.html) { set $unsafe 1; }
|
||||
if ($uri ~ ^/common/onlyoffice/.*/.*\.html) { set $unsafe 1; }
|
||||
if ($uri ~ ^/common/onlyoffice/dist/.*/sdkjs/common/spell/spell/spell.js.*$) { set $unsafe 1; }
|
||||
|
||||
# everything except the sandbox domain is a privileged scope, as they might be used to handle keys
|
||||
if ($host != $sandbox_domain) { set $unsafe 0; }
|
||||
|
||||
151
funding.json
Normal file
151
funding.json
Normal file
@ -0,0 +1,151 @@
|
||||
{
|
||||
"version": "v1.0.0",
|
||||
"drips": {
|
||||
"ethereum": {
|
||||
"ownedBy": "0xa117114b3a22e038c1545043d610dbd4029355b1"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"type": "organisation",
|
||||
"role": "owner",
|
||||
"name": "XWiki SAS",
|
||||
"email": "funding@xwiki.com",
|
||||
"phone": "",
|
||||
"description": "XWiki SAS is a European Open Source organization, maintaining Open Source Collaboration projects, XWiki and CryptPad. We believe that Open Source projects are key to getting back control on software, and that companies are important to allow the maintenance of Open Source projects.",
|
||||
"webpageUrl": {
|
||||
"url": "https://xwiki.com",
|
||||
"wellKnown": "https://xwiki.com/.well-known/funding-manifest-urls"
|
||||
}
|
||||
},
|
||||
"projects": [
|
||||
{
|
||||
"guid": "cryptpad",
|
||||
"name": "CryptPad",
|
||||
"description": "CryptPad is an end-to-end encrypted Collaboration Platform focused on providing real-time editing tools while protecting privacy.",
|
||||
"webpageUrl": {
|
||||
"url": "https://cryptpad.org",
|
||||
"wellKnown": "https://cryptpad.org/.well-known/funding-manifest-urls"
|
||||
},
|
||||
"repositoryUrl": {
|
||||
"url": "https://github.com/cryptpad/cryptpad"
|
||||
},
|
||||
"licenses": [
|
||||
"spdx:AGPL-3.0-or-later"
|
||||
],
|
||||
"tags": [
|
||||
"privacy",
|
||||
"e2ee",
|
||||
"collaboration",
|
||||
"realtimeediting",
|
||||
"office",
|
||||
"drive"
|
||||
]
|
||||
}
|
||||
],
|
||||
"funding": {
|
||||
"channels": [
|
||||
{
|
||||
"guid": "opencollective-cryptpad",
|
||||
"type": "payment-provider",
|
||||
"address": "https://opencollective.com/cryptpad",
|
||||
"description": "OpenCollective CryptPad Account"
|
||||
},
|
||||
{
|
||||
"guid": "bank",
|
||||
"type": "bank",
|
||||
"address": "Contact XWiki SAS",
|
||||
"description": "Donation by Bank Transfer or other means with XWiki SAS"
|
||||
}
|
||||
],
|
||||
"plans": [
|
||||
{
|
||||
"guid": "cryptpad-individual-helper",
|
||||
"status": "active",
|
||||
"name": "Individual Donator - Starter",
|
||||
"description": "Individual Donator would like to help us fund the maintenance and further improvement of the software.\n\n35000 people donating this every year would be needed to fund the current team to allow CryptPad to be independent from outside grants.\n\nThis plans corresponds to:\n\n- an occasional user of CryptPad\n- a regular user with limited funds\n- somebody just wanting to give us a nudge",
|
||||
"amount": 20,
|
||||
"currency": "EUR",
|
||||
"frequency": "yearly",
|
||||
"channels": [
|
||||
"opencollective-cryptpad"
|
||||
]
|
||||
},
|
||||
{
|
||||
"guid": "cryptpad-individual-user",
|
||||
"status": "active",
|
||||
"name": "Individual Donator - User",
|
||||
"description": "Individual Donator would like to help us fund the maintenance and further improvement of the software.\n\n14000 people donating this every year would be needed to fund the current team to allow CryptPad to be independent from outside grants.\n\nThis plans corresponds to:\n\n- an regular user of CryptPad\n- a privacy believer who would like to help us\n- a personal instance owner with limited funds",
|
||||
"amount": 50,
|
||||
"currency": "EUR",
|
||||
"frequency": "yearly",
|
||||
"channels": [
|
||||
"opencollective-cryptpad"
|
||||
]
|
||||
},
|
||||
{
|
||||
"guid": "cryptpad-individual-sponsor",
|
||||
"status": "active",
|
||||
"name": "Individual Donator - Sponsor",
|
||||
"description": "Individual Donator would like to help us fund the maintenance and further improvement of the software.\n\n3500 people donating this every year would be needed to fund the current team to allow CryptPad to be independent from outside grants.\n\nThis plans corresponds to:\n\n- an regular user of CryptPad who really likes CryptPad\n- a privacy believer who wants to accelerate privacy online\n- a personal or community small size instance owner",
|
||||
"amount": 200,
|
||||
"currency": "EUR",
|
||||
"frequency": "yearly",
|
||||
"channels": [
|
||||
"opencollective-cryptpad"
|
||||
]
|
||||
},
|
||||
{
|
||||
"guid": "cryptpad-instanceowner-smallorg",
|
||||
"status": "active",
|
||||
"name": "Small Organization Using CryptPad",
|
||||
"description": "Small Organization which would like to help us fund the maintenance and further improvement of the software.\n\n1500 organizations donating this every year would be needed to fund the current team to allow CryptPad to be independent from outside grants.\n\nThis plans corresponds to:\n\n- a non-profit organization having some funds hosting CryptPad for their members\n- a small company using CryptPad for its users\n- any organizations wanting Privacy software to progress",
|
||||
"amount": 500,
|
||||
"currency": "EUR",
|
||||
"frequency": "yearly",
|
||||
"channels": [
|
||||
"opencollective-cryptpad"
|
||||
]
|
||||
},
|
||||
{
|
||||
"guid": "cryptpad-instanceowner-bigorg",
|
||||
"status": "active",
|
||||
"name": "Small Organization Using CryptPad",
|
||||
"description": "Small Organization which would like to help us fund the maintenance and further improvement of the software.\n\n350 organizations donating this every year would be needed to fund the current team to allow CryptPad to be independent from outside grants.\n\nThis plans corresponds to:\n\n- a commercial company using CryptPad regularly internally or externally\n- any organization having sufficient funds wanting to support Open Source Software doing the right thing\n",
|
||||
"amount": 2000,
|
||||
"currency": "EUR",
|
||||
"frequency": "yearly",
|
||||
"channels": [
|
||||
"opencollective-cryptpad",
|
||||
"bank"
|
||||
]
|
||||
},
|
||||
{
|
||||
"guid": "cryptpad-instanceowner-bigorg",
|
||||
"status": "active",
|
||||
"name": "Organization using CryptPad heavily or as part of their offering",
|
||||
"description": "Organization using CryptPad heavily or as part of it's commercial offering and which would like to significantly contribute to it's development.\n\n70 organizations donating this every year would be needed to fund the current team to allow CryptPad to be independent from outside grants.\n\nThis plans corresponds to:\n\n- a commercial company using CryptPad heavily or as part of a commercial offering\n- foundations who would like to support the development.",
|
||||
"amount": 10000,
|
||||
"currency": "EUR",
|
||||
"frequency": "yearly",
|
||||
"channels": [
|
||||
"opencollective-cryptpad",
|
||||
"bank"
|
||||
]
|
||||
},
|
||||
{
|
||||
"guid": "cryptpad-org-funder",
|
||||
"status": "active",
|
||||
"name": "Funding organization or large company supporting the maintenance and development of CryptPad",
|
||||
"description": "This is meant for an organization investing in Privacy Preserving technologies and/or Open Source software which is important for the internet and wanting to support CryptPad with a grant. The grant can be for specific development useful for our roadmap or just for maintenance of the software.\n\n12 such grants would be needed to fund the current team.",
|
||||
"amount": 50000,
|
||||
"currency": "EUR",
|
||||
"frequency": "one-time",
|
||||
"channels": [
|
||||
"opencollective-cryptpad",
|
||||
"bank"
|
||||
]
|
||||
}
|
||||
],
|
||||
"history": []
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,10 @@ PROPS_FILE="$CONF_DIR"/onlyoffice.properties
|
||||
declare -A PROPS
|
||||
|
||||
main() {
|
||||
|
||||
# clean build env in case a previous build has failed
|
||||
rm -rf "$BUILDS_DIR"
|
||||
|
||||
mkdir -p "$CONF_DIR"
|
||||
|
||||
load_props
|
||||
@ -23,17 +27,18 @@ main() {
|
||||
|
||||
ask_for_license
|
||||
|
||||
# Remeber the 1st version that is installed. This will help us install only
|
||||
# Remember the 1st version that is installed. This will help us install only
|
||||
# needed OnlyOffice versions in a later version of this script.
|
||||
set_prop oldest_needed_version v1
|
||||
|
||||
mkdir -p "$OO_DIR"
|
||||
install_version v1 4f370beb
|
||||
install_version v2b d9da72fd
|
||||
install_version v4 6ebc6938
|
||||
install_version v5 88a356f0
|
||||
install_version v6 abd8a309
|
||||
install_version v7 e1267803
|
||||
install_old_version v1 4f370beb
|
||||
install_old_version v2b d9da72fd
|
||||
install_old_version v4 6ebc6938
|
||||
install_old_version v5 88a356f0
|
||||
install_old_version v6 abd8a309
|
||||
install_version v7 v7.3.3.60+11 1e65be6dc87d97e82b4972f303956e5397b34d637ca80a4239c48e49ab829ee5afc8f5b1680b2fb14230d63ff872ec5f9b562bb6c3f1811316b68f8b436f7ee6
|
||||
install_version v8 v8.3.3.23+4 01abfb3e13dae2066c9fcdc9fd3a3a21cd08212feb7ee2f927d8acaa5c3e560f8ce7c78c533c6aad7048aaecc14f7445891f06cb38a1720e1637a971c0a02295
|
||||
install_x2t v7.3+1 ab0c05b0e4c81071acea83f0c6a8e75f5870c360ec4abc4af09105dd9b52264af9711ec0b7020e87095193ac9b6e20305e446f2321a541f743626a598e5318c1
|
||||
|
||||
rm -rf "$BUILDS_DIR"
|
||||
@ -156,23 +161,22 @@ EOF
|
||||
}
|
||||
|
||||
ensure_oo_is_downloaded() {
|
||||
ensure_command_available git
|
||||
ensure_command_available git
|
||||
|
||||
if ! [ -d "$BUILDS_DIR" ]; then
|
||||
echo "Downloading OnlyOffice..."
|
||||
git clone --bare https://github.com/cryptpad/onlyoffice-builds.git "$BUILDS_DIR"
|
||||
fi
|
||||
if [ ${TRUST_REPOSITORY+x} ] || [ "${PROPS[trust_repository]:-no}" == yes ]; then
|
||||
git config --global --add safe.directory /cryptpad/onlyoffice-conf/onlyoffice-builds.git
|
||||
fi
|
||||
if ! [ -d "$BUILDS_DIR" ]; then
|
||||
echo "Downloading OnlyOffice..."
|
||||
git clone --bare https://github.com/cryptpad/onlyoffice-builds.git "$BUILDS_DIR"
|
||||
fi
|
||||
if [ ${TRUST_REPOSITORY+x} ] || [ "${PROPS[trust_repository]:-no}" == yes ]; then
|
||||
git config --global --add safe.directory /cryptpad/onlyoffice-conf/onlyoffice-builds.git
|
||||
fi
|
||||
}
|
||||
|
||||
install_version() {
|
||||
install_old_version() {
|
||||
local DIR=$1
|
||||
local COMMIT=$2
|
||||
local FULL_DIR=$OO_DIR/$DIR
|
||||
local LAST_DIR
|
||||
LAST_DIR=$(pwd)
|
||||
local LAST_DIR=$(pwd)
|
||||
|
||||
local ACTUAL_COMMIT="not installed"
|
||||
if [ -e "$FULL_DIR"/.commit ]; then
|
||||
@ -206,6 +210,40 @@ install_version() {
|
||||
fi
|
||||
}
|
||||
|
||||
install_version() {
|
||||
ensure_command_available curl
|
||||
ensure_command_available sha512sum
|
||||
ensure_command_available unzip
|
||||
|
||||
local DIR=$1
|
||||
local VERSION=$2
|
||||
local HASH=$3
|
||||
local FULL_DIR=$OO_DIR/$DIR
|
||||
local LAST_DIR=$(pwd)
|
||||
|
||||
if [ ! -e "$FULL_DIR"/.version ] || [ "$(cat "$FULL_DIR"/.version)" != "$VERSION" ]; then
|
||||
rm -rf "$FULL_DIR"
|
||||
mkdir -p "$FULL_DIR"
|
||||
|
||||
cd "$FULL_DIR"
|
||||
|
||||
curl "https://github.com/cryptpad/onlyoffice-editor/releases/download/$VERSION/onlyoffice-editor.zip" --location --output "onlyoffice-editor.zip"
|
||||
echo "$HASH onlyoffice-editor.zip" >onlyoffice-editor.zip.sha512
|
||||
if ! sha512sum --check onlyoffice-editor.zip.sha512; then
|
||||
echo "onlyoffice-editor.zip does not match expected checksum"
|
||||
exit 1
|
||||
fi
|
||||
unzip onlyoffice-editor.zip
|
||||
rm onlyoffice-editor.zip*
|
||||
|
||||
echo "$VERSION" >"$FULL_DIR"/.version
|
||||
|
||||
echo "$DIR updated"
|
||||
else
|
||||
echo "$DIR was up to date"
|
||||
fi
|
||||
}
|
||||
|
||||
install_x2t() {
|
||||
local VERSION=$1
|
||||
local HASH=$2
|
||||
@ -233,7 +271,6 @@ install_x2t() {
|
||||
ensure_command_available sha512sum
|
||||
ensure_command_available unzip
|
||||
curl "https://github.com/cryptpad/onlyoffice-x2t-wasm/releases/download/$VERSION/x2t.zip" --location --output x2t.zip
|
||||
# curl "https://github.com/cryptpad/onlyoffice-x2t-wasm/releases/download/v7.3%2B1/x2t.zip" --location --output x2t.zip
|
||||
echo "$HASH x2t.zip" >x2t.zip.sha512
|
||||
if ! sha512sum --check x2t.zip.sha512; then
|
||||
echo "x2t.zip does not match expected checksum"
|
||||
|
||||
@ -12,6 +12,7 @@ const Fse = require("fs-extra");
|
||||
const Path = require("path");
|
||||
const Nacl = require("tweetnacl/nacl-fast");
|
||||
const Hash = require('./common-hash');
|
||||
const Util = require('./common-util');
|
||||
|
||||
module.exports.create = function (Env) {
|
||||
var log = Env.Log;
|
||||
@ -92,7 +93,7 @@ nThen(function (w) {
|
||||
if (typeof(Env.bearerSecret) === 'string') { return; }
|
||||
// if one does not exist, then create one and remember it
|
||||
// 256 bits
|
||||
var bearerSecret = Nacl.util.encodeBase64(Nacl.randomBytes(32));
|
||||
var bearerSecret = Util.encodeBase64(Nacl.randomBytes(32));
|
||||
Env.Log.info("GENERATING_BEARER_SECRET", {});
|
||||
Decrees.write(Env, [
|
||||
'SET_BEARER_SECRET',
|
||||
|
||||
@ -44,14 +44,14 @@ Block.validateLoginBlock = function (Env, publicKey, signature, block, _cb) {
|
||||
|
||||
var u8_public_key;
|
||||
try {
|
||||
u8_public_key = Nacl.util.decodeBase64(publicKey);
|
||||
u8_public_key = Util.decodeBase64(publicKey);
|
||||
} catch (e) {
|
||||
return void cb('E_INVALID_KEY');
|
||||
}
|
||||
|
||||
var u8_signature;
|
||||
try {
|
||||
u8_signature = Nacl.util.decodeBase64(signature);
|
||||
u8_signature = Util.decodeBase64(signature);
|
||||
} catch (e) {
|
||||
Env.Log.error('INVALID_BLOCK_SIGNATURE', e);
|
||||
return void cb('E_INVALID_SIGNATURE');
|
||||
@ -60,7 +60,7 @@ Block.validateLoginBlock = function (Env, publicKey, signature, block, _cb) {
|
||||
// convert the block to a Uint8Array
|
||||
var u8_block;
|
||||
try {
|
||||
u8_block = Nacl.util.decodeBase64(block);
|
||||
u8_block = Util.decodeBase64(block);
|
||||
} catch (e) {
|
||||
return void cb('E_INVALID_BLOCK');
|
||||
}
|
||||
@ -85,9 +85,9 @@ Block.validateAncestorProof = function (Env, proof, _cb) {
|
||||
try {
|
||||
var parsed = JSON.parse(proof);
|
||||
var pub = parsed[0];
|
||||
var u8_pub = Nacl.util.decodeBase64(pub);
|
||||
var u8_pub = Util.decodeBase64(pub);
|
||||
var sig = parsed[1];
|
||||
var u8_sig = Nacl.util.decodeBase64(sig);
|
||||
var u8_sig = Util.decodeBase64(sig);
|
||||
var valid = false;
|
||||
nThen(function (w) {
|
||||
valid = Nacl.sign.detached.verify(u8_pub, u8_sig, u8_pub);
|
||||
@ -159,7 +159,7 @@ Block.writeLoginBlock = function (Env, msg, _cb) {
|
||||
}).nThen(function () {
|
||||
var buffer;
|
||||
try {
|
||||
buffer = Buffer.from(Nacl.util.decodeBase64(validatedBlock));
|
||||
buffer = Buffer.from(Util.decodeBase64(validatedBlock));
|
||||
} catch (err) {
|
||||
return void cb('E_BLOCK_DESERIALIZATION');
|
||||
}
|
||||
|
||||
@ -225,8 +225,8 @@ Channel.deleteMailboxMessage = function (Env, data, cb) {
|
||||
const proof = data.proof;
|
||||
let nonce, proofBytes;
|
||||
try {
|
||||
nonce = Nacl.util.decodeBase64(proof.split('|')[0]);
|
||||
proofBytes = Nacl.util.decodeBase64(proof.split('|')[1]);
|
||||
nonce = Util.decodeBase64(proof.split('|')[0]);
|
||||
proofBytes = Util.decodeBase64(proof.split('|')[1]);
|
||||
} catch (e) {
|
||||
return void cb('EINVAL');
|
||||
}
|
||||
@ -234,10 +234,10 @@ Channel.deleteMailboxMessage = function (Env, data, cb) {
|
||||
// Check if you're allowed to delete this hash
|
||||
try {
|
||||
const mySecret = Env.curvePrivate;
|
||||
const msgBytes = Nacl.util.decodeBase64(msg).subarray(64); // Remove signature
|
||||
const msgBytes = Util.decodeBase64(msg).subarray(64); // Remove signature
|
||||
const theirPublic = msgBytes.subarray(24,56); // 0-24 = nonce; 24-56=publickey (32 bytes)
|
||||
const hashBytes = Nacl.box.open(proofBytes, nonce, theirPublic, mySecret);
|
||||
return Nacl.util.encodeUTF8(hashBytes) === hash;
|
||||
return Util.encodeUTF8(hashBytes) === hash;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -309,3 +309,9 @@ Pinning.getDeletedPads = function (Env, channels, cb) {
|
||||
Pinning.isChannelPinned = function (Env, channel, cb) {
|
||||
return void cb(void 0, true);
|
||||
};
|
||||
|
||||
Pinning.isPremium = function (Env, userKey, cb) {
|
||||
const limit = Env.limits[userKey];
|
||||
return void cb(void 0, !!limit?.plan);
|
||||
//return void cb(void 0, (limit?.plan && limit.plan !== "custom"));
|
||||
};
|
||||
|
||||
@ -57,6 +57,7 @@ Default.httpHeaders = function (Env) {
|
||||
"X-XSS-Protection": "1; mode=block",
|
||||
"X-Content-Type-Options": "nosniff",
|
||||
"Access-Control-Allow-Origin": Env.enableEmbedding? '*': Env.permittedEmbedders,
|
||||
"Referrer-Policy": "same-origin",
|
||||
"Permissions-policy":"interest-cohort=()"
|
||||
};
|
||||
};
|
||||
|
||||
@ -254,7 +254,7 @@ module.exports.create = function (config) {
|
||||
// initialized as undefined
|
||||
bearerSecret: void 0,
|
||||
curvePrivate: curve.secretKey,
|
||||
curvePublic: Nacl.util.encodeBase64(curve.publicKey),
|
||||
curvePublic: Util.encodeBase64(curve.publicKey),
|
||||
|
||||
selfDestructTo: {},
|
||||
};
|
||||
|
||||
127
lib/eviction.js
127
lib/eviction.js
@ -8,9 +8,7 @@ var Util = require("../lib/common-util");
|
||||
var Pins = require("../lib/pins");
|
||||
var Keys = require("./keys");
|
||||
var Path = require('node:path');
|
||||
var config = require("./load-config");
|
||||
var Fs = require("node:fs");
|
||||
var Fse = require("fs-extra");
|
||||
|
||||
var getNewestTime = function (stats) {
|
||||
return stats[['atime', 'ctime', 'mtime'].reduce(function (a, b) {
|
||||
@ -76,103 +74,6 @@ var evictArchived = function (Env, cb) {
|
||||
blobs = Env.blobStore;
|
||||
};
|
||||
|
||||
var migrateBlobRoot = function (from, to) {
|
||||
// only migrate subpaths, leave everything else alone
|
||||
if (!Path.dirname(from).startsWith(Path.dirname(to))) { return; }
|
||||
|
||||
// expects a directory
|
||||
var recurse = function (relativePath) {
|
||||
var src = Path.join(from, relativePath);
|
||||
var children;
|
||||
try {
|
||||
children = Fs.readdirSync(src);
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') { return; }
|
||||
// if you can't read a directory's contents
|
||||
// then nothing else will work, so just abort
|
||||
Log.verbose("EVICT_ARCHIVED_NOT_DIRECTORY", {
|
||||
error: err,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var dest;
|
||||
if (children.length === 0) {
|
||||
try {
|
||||
Fse.removeSync(src);
|
||||
} catch (err2) {
|
||||
Log.error('EVICT_ARCHIVED_EMPTY_DIR_REMOVAL', {
|
||||
error: err2,
|
||||
});
|
||||
// removal is non-essential, so we can continue
|
||||
}
|
||||
} else {
|
||||
// make an equivalent path in the target directory
|
||||
dest = Path.join(to, relativePath);
|
||||
|
||||
try {
|
||||
Fse.mkdirpSync(dest);
|
||||
} catch (err3) {
|
||||
Log.error("EVICT_ARCHIVED_BLOB_MIGRATION", {
|
||||
error: err3,
|
||||
});
|
||||
|
||||
// failure to create the host directory
|
||||
// will cause problems when we try to move
|
||||
// so bail out here
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
children.forEach(function (child) {
|
||||
var childSrcPath = Path.join(src, child);
|
||||
var stat = Fs.statSync(childSrcPath);
|
||||
if (stat.isDirectory()) {
|
||||
return void recurse(Path.join(relativePath, child));
|
||||
}
|
||||
|
||||
var childDestPath = Path.join(dest, child);
|
||||
|
||||
try {
|
||||
Log.verbose("EVICT_ARCHIVED_MOVE_FROM_DEPRECATED_PATH", {
|
||||
from: childSrcPath,
|
||||
to: childDestPath,
|
||||
});
|
||||
Fse.moveSync(childSrcPath, childDestPath, {
|
||||
overwrite: false,
|
||||
});
|
||||
} catch (err4) {
|
||||
Log.error('EVICT_ARCHIVED_MOVE_FAILURE', {
|
||||
error: err4,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
recurse('');
|
||||
};
|
||||
|
||||
/* In CryptPad 5.2.0 we merged a patch which converted
|
||||
all of CryptPad's root filepaths to their absolute form,
|
||||
rather than the relative paths we'd been using until then.
|
||||
Unfortunately, we overlooked a case where two absolute
|
||||
paths were concatenated together, resulting in blobs being
|
||||
archived to an incorrect path.
|
||||
|
||||
This migration detects evidence of incorrect archivals
|
||||
and moves such archived files to their intended location
|
||||
before continuing with the normal eviction procedure.
|
||||
*/
|
||||
var migrateIncorrectBlobs = function () {
|
||||
var incorrectPaths = [
|
||||
Path.join(Env.paths.archive, config.blobPath),
|
||||
Path.join(Env.paths.archive, Path.resolve(config.blobPath))
|
||||
];
|
||||
var correctPath = Path.join(Env.paths.archive, 'blob');
|
||||
incorrectPaths.forEach(root => {
|
||||
migrateBlobRoot(root, correctPath);
|
||||
});
|
||||
};
|
||||
|
||||
var removeArchivedChannels = function (w) {
|
||||
// this block will iterate over archived channels and removes them
|
||||
// if they've been in cold storage for longer than your configured archive time
|
||||
@ -236,6 +137,30 @@ var evictArchived = function (Env, cb) {
|
||||
store.listArchivedChannels(handler, w(done));
|
||||
};
|
||||
|
||||
// Blob proofs are no longer supported and can't be restored
|
||||
// so we can delete them all
|
||||
var removeArchivedBlobProofs = function (w) {
|
||||
var archivePath = Path.join(Env.paths.archive, 'blob');
|
||||
const cb = Util.once(w());
|
||||
let i = 0;
|
||||
nThen(w => {
|
||||
Fs.readdir(archivePath, w((err, list) => {
|
||||
if (err) { return; }
|
||||
list.forEach(dir => {
|
||||
// Look for 3 characters long folders
|
||||
if (dir.length !== 3) { return; }
|
||||
let path = Path.join(archivePath, dir);
|
||||
Fs.rm(path, { recursive: true, force: true }, w(err => {
|
||||
if (err) { return; }
|
||||
i++;
|
||||
}));
|
||||
});
|
||||
}));
|
||||
}).nThen(() => {
|
||||
Log.info('EVICT_ARCHIVED_BLOB_PROOFS', i);
|
||||
cb();
|
||||
});
|
||||
};
|
||||
var removeArchivedBlobs = function (w) {
|
||||
if (typeof(Env.archiveRetentionTime) !== "number") { return; }
|
||||
// Iterate over archived blobs and remove them
|
||||
@ -269,8 +194,8 @@ var evictArchived = function (Env, cb) {
|
||||
|
||||
if (Env.DRY_RUN) { Env.Log.info('DRY RUN'); }
|
||||
nThen(loadStorage)
|
||||
.nThen(migrateIncorrectBlobs)
|
||||
.nThen(removeArchivedChannels)
|
||||
.nThen(removeArchivedBlobProofs)
|
||||
.nThen(removeArchivedBlobs)
|
||||
.nThen(function () {
|
||||
cb(void 0, report);
|
||||
@ -588,7 +513,7 @@ module.exports = function (Env, cb) {
|
||||
if (newerItem && getNewestTime(newerItem) > retentionTime) {
|
||||
// it's actually active, so don't archive it.
|
||||
w.abort();
|
||||
cb();
|
||||
next();
|
||||
}
|
||||
// else fall through to the archival
|
||||
}));
|
||||
|
||||
@ -116,7 +116,7 @@ HK.closeNetfluxSession = function (Env, netfluxId) {
|
||||
const isValidValidateKeyString = function (key) {
|
||||
try {
|
||||
return typeof(key) === 'string' &&
|
||||
Nacl.util.decodeBase64(key).length === Nacl.sign.publicKeyLength;
|
||||
Util.decodeBase64(key).length === Nacl.sign.publicKeyLength;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ COMMANDS.SSO_UPDATE_BLOCK = SSO.SSO_UPDATE_BLOCK; // Password change
|
||||
COMMANDS.SSO_VALIDATE = SSO.SSO_VALIDATE;
|
||||
*/
|
||||
|
||||
var randomToken = () => Nacl.util.encodeBase64(Nacl.randomBytes(24)).replace(/\//g, '-');
|
||||
var randomToken = () => Util.encodeBase64(Nacl.randomBytes(24)).replace(/\//g, '-');
|
||||
|
||||
// this function handles the first stage of the protocol
|
||||
// (the server's validation of the client's request and the generation of its challenge)
|
||||
@ -278,9 +278,9 @@ var handleResponse = function (Env, req, res) {
|
||||
u8_publicKey;
|
||||
|
||||
try {
|
||||
u8_toVerify = Nacl.util.decodeUTF8(text);
|
||||
u8_sig = Nacl.util.decodeBase64(sig);
|
||||
u8_publicKey = Nacl.util.decodeBase64(publicKey);
|
||||
u8_toVerify = Util.decodeUTF8(text);
|
||||
u8_sig = Util.decodeBase64(sig);
|
||||
u8_publicKey = Util.decodeBase64(publicKey);
|
||||
} catch (err3) {
|
||||
Env.Log.error('CHALLENGE_RESPONSE_DECODING_ERROR', {
|
||||
text: text,
|
||||
|
||||
@ -18,6 +18,7 @@ const bodyParser = require('body-parser');
|
||||
const BlobStore = require("./storage/blob");
|
||||
const BlockStore = require("./storage/block");
|
||||
const plugins = require("./plugin-manager");
|
||||
const gzipStatic = require('connect-gzip-static');
|
||||
|
||||
const DEFAULT_QUERY_TIMEOUT = 5000;
|
||||
const PID = process.pid;
|
||||
@ -134,6 +135,7 @@ var applyHeaderMap = function (res, map) {
|
||||
|
||||
var EXEMPT = [
|
||||
/^\/common\/onlyoffice\/.*\.html.*/,
|
||||
/^\/common\/onlyoffice\/dist\/.*\/sdkjs\/common\/spell\/spell\/spell.js.*/, // OnlyOffice loads spell.wasm in a way that needs unsave-eval
|
||||
/^\/(sheet|presentation|doc)\/inner\.html.*/,
|
||||
/^\/unsafeiframe\/inner\.html.*$/,
|
||||
];
|
||||
@ -336,7 +338,7 @@ Object.keys(plugins || {}).forEach(name => {
|
||||
// serve custom app content from the customize directory
|
||||
// useful for testing pages customized with opengraph data
|
||||
app.use(Express.static(Path.resolve('./customize/www')));
|
||||
app.use(Express.static(Path.resolve('./www')));
|
||||
app.use(gzipStatic(Path.resolve('./www')));
|
||||
|
||||
var mainPages = Env.mainPages || Default.mainPages();
|
||||
var mainPagePattern = new RegExp('^\/(' + mainPages.join('|') + ').html$');
|
||||
|
||||
30
lib/pins.js
30
lib/pins.js
@ -8,6 +8,7 @@ const Fs = require("fs");
|
||||
const Path = require("path");
|
||||
const Util = require("./common-util");
|
||||
const Plan = require("./plan");
|
||||
const Store = require('./storage/file');
|
||||
|
||||
const Semaphore = require('saferphore');
|
||||
const nThen = require('nthen');
|
||||
@ -258,8 +259,20 @@ Pins.load = function (cb, config) {
|
||||
var pinPath = config.pinPath || './pins';
|
||||
var done = Util.once(cb);
|
||||
var handler = config.handler;
|
||||
let store;
|
||||
|
||||
nThen((waitFor) => {
|
||||
Store.create({
|
||||
filePath: config.pinPath,
|
||||
volumeId: 'pins'
|
||||
}, waitFor((err, _) => {
|
||||
if (err) {
|
||||
waitFor.abort();
|
||||
return void done(err);
|
||||
}
|
||||
store = _;
|
||||
}));
|
||||
}).nThen((waitFor) => {
|
||||
// recurse over the configured pinPath, or the default
|
||||
Fs.readdir(pinPath, waitFor((err, list) => {
|
||||
if (err) {
|
||||
@ -283,26 +296,29 @@ Pins.load = function (cb, config) {
|
||||
}
|
||||
list2.forEach((ff) => {
|
||||
if (config && config.exclude && config.exclude.indexOf(ff) > -1) { return; }
|
||||
fileList.push(Path.join(pinPath, f, ff));
|
||||
fileList.push(ff.replace(/(\.ndjson)$/, ''));
|
||||
});
|
||||
})));
|
||||
});
|
||||
});
|
||||
}).nThen((waitFor) => {
|
||||
fileList.forEach((f) => {
|
||||
fileList.forEach((id) => {
|
||||
sema.take((returnAfter) => {
|
||||
var next = waitFor(returnAfter());
|
||||
Fs.readFile(f, (err, content) => {
|
||||
var ref = {};
|
||||
var h = createLineHandler(ref, id);
|
||||
store.readMessagesBin(id, 0, (msgObj, next) => {
|
||||
h(msgObj.buff.toString('utf8'));
|
||||
next();
|
||||
}, (err) => {
|
||||
if (err) {
|
||||
waitFor.abort();
|
||||
return void done(err);
|
||||
}
|
||||
var id = f.replace(/.*\/([^/]*).ndjson$/, (x, y)=>y);
|
||||
var contentString = content.toString('utf8');
|
||||
if (handler) {
|
||||
return void handler(processPinFile(contentString, f), id, next);
|
||||
return void handler(ref, id, next);
|
||||
}
|
||||
const hashes = Pins.calculateFromLog(contentString, f);
|
||||
const hashes = Object.keys(ref.pins);
|
||||
hashes.forEach((x) => {
|
||||
(pinned[x] = pinned[x] || {})[id] = 1;
|
||||
});
|
||||
|
||||
@ -24,6 +24,7 @@ const UNAUTHENTICATED_CALLS = {
|
||||
WRITE_PRIVATE_MESSAGE: Channel.writePrivateMessage,
|
||||
DELETE_MAILBOX_MESSAGE: Channel.deleteMailboxMessage,
|
||||
GET_METADATA: Metadata.getMetadata,
|
||||
IS_PREMIUM: Pinning.isPremium,
|
||||
ADD_FIRST_ADMIN: Admin.addFirstAdmin
|
||||
};
|
||||
|
||||
|
||||
@ -473,9 +473,29 @@ var archiveBlob = function (Env, blobId, reason, cb) {
|
||||
};
|
||||
|
||||
var removeArchivedBlob = function (Env, blobId, cb) {
|
||||
var CB = Util.once(cb);
|
||||
var archivePath = prependArchive(Env, makeBlobPath(Env, blobId));
|
||||
var metadataPath = prependArchive(Env, mkMetadataPath(Env, blobId));
|
||||
Fs.unlink(archivePath, cb);
|
||||
removeArchivedActivity(Env, blobId, () => {});
|
||||
nThen(function (w) {
|
||||
Fs.unlink(archivePath, w(function (err) {
|
||||
if (err) {
|
||||
if (err.code === "ENOENT") { return; }
|
||||
w.abort();
|
||||
CB("E_ARCHIVED_BLOB_REMOVAL_"+ err.code);
|
||||
}
|
||||
}));
|
||||
Fs.unlink(metadataPath, w(function (err) {
|
||||
if (err) {
|
||||
if (err.code === "ENOENT") { return; }
|
||||
w.abort();
|
||||
CB("E_ARCHIVED_BLOBMD_REMOVAL_"+ err.code);
|
||||
}
|
||||
}));
|
||||
removeArchivedActivity(Env, blobId, () => {});
|
||||
}).nThen(function () {
|
||||
CB();
|
||||
});
|
||||
};
|
||||
|
||||
// restoreBlob
|
||||
|
||||
@ -573,6 +573,7 @@ var removeArchivedChannel = function (env, channelName, cb) {
|
||||
nThen(function (w) {
|
||||
Fs.unlink(channelPath, w(function (err) {
|
||||
if (err) {
|
||||
if (err.code === "ENOENT") { return; }
|
||||
w.abort();
|
||||
CB(labelError("E_ARCHIVED_CHANNEL_REMOVAL", err));
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ var pathFromId = function (Env, id, ref) {
|
||||
return Path.join(Env.paths.base, "sessions", id.slice(0, 2), id, ref);
|
||||
};
|
||||
|
||||
Sessions.randomId = () => Nacl.util.encodeBase64(Nacl.randomBytes(24)).replace(/\//g, '-');
|
||||
Sessions.randomId = () => Util.encodeBase64(Nacl.randomBytes(24)).replace(/\//g, '-');
|
||||
|
||||
Sessions.read = function (Env, id, ref, cb) {
|
||||
var path = pathFromId(Env, id, ref);
|
||||
|
||||
@ -7,6 +7,7 @@ var Fse = require("fs-extra");
|
||||
var Path = require("path");
|
||||
var nacl = require("tweetnacl/nacl-fast");
|
||||
var nThen = require("nthen");
|
||||
var Util = require('../common-util');
|
||||
|
||||
var Tasks = module.exports;
|
||||
|
||||
@ -49,7 +50,7 @@ var makeDirectoryId = function (d) {
|
||||
|
||||
var write = function (env, task, cb) {
|
||||
var str = JSON.stringify(task) + '\n';
|
||||
var id = nacl.util.encodeBase64(nacl.hash(nacl.util.decodeUTF8(str))).replace(/\//g, '-');
|
||||
var id = Util.encodeBase64(nacl.hash(Util.decodeUTF8(str))).replace(/\//g, '-');
|
||||
|
||||
var dir = makeDirectoryId(task[0]);
|
||||
var path = Path.join(env.root, dir);
|
||||
|
||||
@ -772,14 +772,14 @@ COMMANDS.INLINE = function (data, cb) {
|
||||
monitoringIncrement('inlineValidation');
|
||||
var signedMsg;
|
||||
try {
|
||||
signedMsg = Nacl.util.decodeBase64(data.msg);
|
||||
signedMsg = Util.decodeBase64(data.msg);
|
||||
} catch (e) {
|
||||
return void cb('E_BAD_MESSAGE');
|
||||
}
|
||||
|
||||
var validateKey;
|
||||
try {
|
||||
validateKey = Nacl.util.decodeBase64(data.key);
|
||||
validateKey = Util.decodeBase64(data.key);
|
||||
} catch (e) {
|
||||
return void cb("E_BADKEY");
|
||||
}
|
||||
@ -801,19 +801,19 @@ const checkDetachedSignature = function (signedMsg, signature, publicKey) {
|
||||
var signatureBuffer;
|
||||
|
||||
try {
|
||||
signedBuffer = Nacl.util.decodeUTF8(signedMsg);
|
||||
signedBuffer = Util.decodeUTF8(signedMsg);
|
||||
} catch (e) {
|
||||
throw new Error("INVALID_SIGNED_BUFFER");
|
||||
}
|
||||
|
||||
try {
|
||||
pubBuffer = Nacl.util.decodeBase64(publicKey);
|
||||
pubBuffer = Util.decodeBase64(publicKey);
|
||||
} catch (e) {
|
||||
throw new Error("INVALID_PUBLIC_KEY");
|
||||
}
|
||||
|
||||
try {
|
||||
signatureBuffer = Nacl.util.decodeBase64(signature);
|
||||
signatureBuffer = Util.decodeBase64(signature);
|
||||
} catch (e) {
|
||||
throw new Error("INVALID_SIGNATURE");
|
||||
}
|
||||
@ -851,8 +851,7 @@ COMMANDS.HASH_CHANNEL_LIST = function (data, cb) {
|
||||
});
|
||||
uniques.sort();
|
||||
|
||||
var hash = Nacl.util.encodeBase64(Nacl.hash(Nacl
|
||||
.util.decodeUTF8(JSON.stringify(uniques))));
|
||||
var hash = Util.encodeBase64(Nacl.hash(Util.decodeUTF8(JSON.stringify(uniques))));
|
||||
|
||||
cb(void 0, hash);
|
||||
};
|
||||
|
||||
@ -53,7 +53,7 @@ Workers.initialize = function (Env, config, _cb) {
|
||||
//return Object.keys(workers[index].tasks || {}).length;
|
||||
};
|
||||
|
||||
const WORKER_TASK_LIMIT = 100000; // XXX
|
||||
const WORKER_TASK_LIMIT = 250000; // XXX
|
||||
|
||||
var workerOffset = -1;
|
||||
var queue = [];
|
||||
@ -260,6 +260,16 @@ Workers.initialize = function (Env, config, _cb) {
|
||||
pid: worker.pid, // store the child process's id in an easily accessible location
|
||||
};
|
||||
|
||||
let pid = worker.pid;
|
||||
const onWorkerClosed = () => {
|
||||
Object.keys(Env.plugins || {}).forEach(name => {
|
||||
let plugin = Env.plugins[name];
|
||||
if (!plugin.onWorkerClosed) { return; }
|
||||
try { plugin.onWorkerClosed("db-worker", pid); }
|
||||
catch (e) {}
|
||||
});
|
||||
};
|
||||
|
||||
state.replaceWorker = () => {
|
||||
let index = workers.indexOf(state);
|
||||
if (index === -1) { return; }
|
||||
@ -291,6 +301,7 @@ Workers.initialize = function (Env, config, _cb) {
|
||||
worker: state.worker.pid,
|
||||
count: state.count
|
||||
});
|
||||
onWorkerClosed();
|
||||
delete state.worker;
|
||||
worker.kill();
|
||||
};
|
||||
@ -323,14 +334,8 @@ Workers.initialize = function (Env, config, _cb) {
|
||||
handleResponse(state, res);
|
||||
});
|
||||
|
||||
let pid = worker.pid;
|
||||
var substituteWorker = Util.once(function () {
|
||||
Object.keys(Env.plugins || {}).forEach(name => {
|
||||
let plugin = Env.plugins[name];
|
||||
if (!plugin.onWorkerClosed) { return; }
|
||||
try { plugin.onWorkerClosed("db-worker", pid); }
|
||||
catch (e) {}
|
||||
});
|
||||
onWorkerClosed();
|
||||
|
||||
Env.Log.info("SUBSTITUTE_DB_WORKER", '');
|
||||
var idx = workers.indexOf(state);
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
// merge code more easily.
|
||||
// Set REVERSE to true to copy from "www" to "src" once the changes have been merged.
|
||||
|
||||
const REVERSE = true;
|
||||
const REVERSE = false;
|
||||
const Fs = require('node:fs');
|
||||
const map = {
|
||||
'./src/worker/components/roster.js': './www/common/outer/roster.js',
|
||||
@ -20,7 +20,6 @@ const map = {
|
||||
'./src/common/common-credential.js': './www/common/common-credential.js',
|
||||
'./src/common/common-feedback.js': './www/common/common-feedback.js',
|
||||
'./src/common/common-hash.js': './www/common/common-hash.js',
|
||||
'./src/common/common-messaging.js': './www/common/common-messaging.js',
|
||||
'./src/common/common-realtime.js': './www/common/common-realtime.js',
|
||||
'./src/common/common-signing-keys.js': './www/common/common-signing-keys.js',
|
||||
'./src/common/common-util.js': './www/common/common-util.js',
|
||||
|
||||
82
package-lock.json
generated
82
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "cryptpad",
|
||||
"version": "2025.3.0",
|
||||
"version": "2025.3.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "cryptpad",
|
||||
"version": "2025.3.0",
|
||||
"version": "2025.3.1",
|
||||
"license": "AGPL-3.0+",
|
||||
"dependencies": {
|
||||
"@mcrowe/minibloom": "^0.2.0",
|
||||
@ -16,13 +16,14 @@
|
||||
"bootstrap": "^4.0.0",
|
||||
"bootstrap-tokenfield": "^0.12.0",
|
||||
"chainpad": "^5.2.6",
|
||||
"chainpad-crypto": "^0.2.5",
|
||||
"chainpad-listmap": "^1.1.1",
|
||||
"chainpad-netflux": "^1.2.3",
|
||||
"chainpad-crypto": "^0.3.0",
|
||||
"chainpad-listmap": "^1.2.0",
|
||||
"chainpad-netflux": "^1.3.0",
|
||||
"chainpad-server": "^5.2.4",
|
||||
"ckeditor": "npm:ckeditor4@~4.22.1",
|
||||
"codemirror": "^5.19.0",
|
||||
"components-font-awesome": "^4.6.3",
|
||||
"connect-gzip-static": "^4.2.1",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"croppie": "^2.5.0",
|
||||
"dragula": "3.7.2",
|
||||
@ -58,7 +59,8 @@
|
||||
"sortify": "^1.0.4",
|
||||
"stream-to-pull-stream": "^1.7.2",
|
||||
"thirty-two": "^1.0.2",
|
||||
"tweetnacl": "file:./src/tweetnacl",
|
||||
"tweetnacl": "^1.0.3",
|
||||
"tweetnacl-util": "^0.15.1",
|
||||
"ulimit": "0.0.2",
|
||||
"ws": "^8.17.1",
|
||||
"x2js": "^3.4.4"
|
||||
@ -1902,19 +1904,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chainpad-crypto": {
|
||||
"version": "0.2.8",
|
||||
"resolved": "https://registry.npmjs.org/chainpad-crypto/-/chainpad-crypto-0.2.8.tgz",
|
||||
"integrity": "sha512-B0/aW0TUcRQUF8Aaz7bBFfIPs/ybdr92Rl0ezVrSxEQuxaRHBNGJrUvVxdKreLuh+XYdbQeeRKDXbgvEcLDcEg==",
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/chainpad-crypto/-/chainpad-crypto-0.3.0.tgz",
|
||||
"integrity": "sha512-L6gUiE8m/ZrUE3eVMju6qzG92Mis3M4T1xCuxVF3eqwa9+46fl9OFwt/TiSmi+oVHSIBmgDTcnOEF/JSxnxYxw==",
|
||||
"license": "AGPL-3.0+",
|
||||
"dependencies": {
|
||||
"tweetnacl": "~0.12.2"
|
||||
"tweetnacl": "^1.0.3",
|
||||
"tweetnacl-util": "^0.15.1"
|
||||
}
|
||||
},
|
||||
"node_modules/chainpad-listmap": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chainpad-listmap/-/chainpad-listmap-1.1.1.tgz",
|
||||
"integrity": "sha512-SXb3iJqWyp2wOMa9FT4kqOuR1KgjMPcNCzLlYignu1GdxMI67ZDGTLDucmht4CD8yuYzUWzWmJgs1vs/acH+rw==",
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/chainpad-listmap/-/chainpad-listmap-1.2.0.tgz",
|
||||
"integrity": "sha512-PI7iwk/yKzEb1iaVmLKvMJYXjCjvIgUWzI07LeDGVvZPScnYbEzMso9YMQyxzjqrp8cyQxsL7sA8c/hZAz01cw==",
|
||||
"license": "AGPL-3.0+",
|
||||
"dependencies": {
|
||||
"chainpad-netflux": "^1.2.0",
|
||||
"chainpad-netflux": "^1.3.0",
|
||||
"json.sortify": "~2.1.0"
|
||||
}
|
||||
},
|
||||
@ -1927,12 +1932,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chainpad-netflux": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/chainpad-netflux/-/chainpad-netflux-1.2.3.tgz",
|
||||
"integrity": "sha512-bXLUSxAsCu4kRnGorW+7fVofiCWSNGRkB+uFJ4kUV/zDJ3RJYU4J3+DZsL4rCTkLkAjgKt+YQCoYciCKLlTwqg==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/chainpad-netflux/-/chainpad-netflux-1.3.0.tgz",
|
||||
"integrity": "sha512-oc47vLt78a/Fp7acQJvLNuX1JRrH9oOWAbzo+yOO1asCWDuI4oesPY81wHzVySKpo58GGfNpZN7CSTI8EZjYrQ==",
|
||||
"license": "LGPL-2.1",
|
||||
"dependencies": {
|
||||
"netflux-websocket": "^1.2.0"
|
||||
"netflux-websocket": "^1.2.0",
|
||||
"tweetnacl": "^1.0.3",
|
||||
"tweetnacl-util": "^0.15.1"
|
||||
}
|
||||
},
|
||||
"node_modules/chainpad-server": {
|
||||
@ -2060,6 +2067,22 @@
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/connect-gzip-static": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/connect-gzip-static/-/connect-gzip-static-4.2.1.tgz",
|
||||
"integrity": "sha512-6qC1NYUEZU6mftg2gPspcoPjgBzADm+fB1fPXu3RxBVe59P/Q9HQGQEHnuDaGRDJUoJwl5NX2OgoaaZp7RdpfQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "~2||~3||~4",
|
||||
"mime-types": "~2",
|
||||
"parseurl": "~1",
|
||||
"send": "~0 || ~1",
|
||||
"serve-static": "~1 || ~2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
|
||||
@ -3267,9 +3290,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/http-proxy-middleware": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.3.tgz",
|
||||
"integrity": "sha512-usY0HG5nyDUwtqpiZdETNbmKtw3QQ1jwYFZ9wi5iHzX2BcILwQKtYDJPo7XHTsu5Z0B2Hj3W9NNnbd+AjFWjqg==",
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.5.tgz",
|
||||
"integrity": "sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/http-proxy": "^1.17.15",
|
||||
"debug": "^4.3.6",
|
||||
@ -6149,8 +6173,16 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tweetnacl": {
|
||||
"resolved": "src/tweetnacl",
|
||||
"link": true
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
|
||||
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==",
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/tweetnacl-util": {
|
||||
"version": "0.15.1",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz",
|
||||
"integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==",
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
@ -6497,10 +6529,6 @@
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"src/tweetnacl": {
|
||||
"version": "0.12.2",
|
||||
"license": "Public domain"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
12
package.json
12
package.json
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "cryptpad",
|
||||
"description": "a collaborative office suite that is end-to-end encrypted and open-source",
|
||||
"version": "2025.3.0",
|
||||
"version": "2025.3.1",
|
||||
"license": "AGPL-3.0+",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -19,13 +19,14 @@
|
||||
"bootstrap": "^4.0.0",
|
||||
"bootstrap-tokenfield": "^0.12.0",
|
||||
"chainpad": "^5.2.6",
|
||||
"chainpad-crypto": "^0.2.5",
|
||||
"chainpad-listmap": "^1.1.1",
|
||||
"chainpad-netflux": "^1.2.3",
|
||||
"chainpad-crypto": "^0.3.0",
|
||||
"chainpad-listmap": "^1.2.0",
|
||||
"chainpad-netflux": "^1.3.0",
|
||||
"chainpad-server": "^5.2.4",
|
||||
"ckeditor": "npm:ckeditor4@~4.22.1",
|
||||
"codemirror": "^5.19.0",
|
||||
"components-font-awesome": "^4.6.3",
|
||||
"connect-gzip-static": "^4.2.1",
|
||||
"cookie-parser": "^1.4.7",
|
||||
"croppie": "^2.5.0",
|
||||
"dragula": "3.7.2",
|
||||
@ -61,7 +62,8 @@
|
||||
"sortify": "^1.0.4",
|
||||
"stream-to-pull-stream": "^1.7.2",
|
||||
"thirty-two": "^1.0.2",
|
||||
"tweetnacl": "file:./src/tweetnacl",
|
||||
"tweetnacl": "^1.0.3",
|
||||
"tweetnacl-util": "^0.15.1",
|
||||
"ulimit": "0.0.2",
|
||||
"ws": "^8.17.1",
|
||||
"x2js": "^3.4.4"
|
||||
|
||||
@ -7,6 +7,7 @@ const nThen = require('nthen');
|
||||
const Nacl = require('tweetnacl/nacl-fast');
|
||||
const Path = require('path');
|
||||
const Pins = require('../lib/pins');
|
||||
const Util = require('../lib/common-util');
|
||||
const Config = require('../lib/load-config');
|
||||
|
||||
var escapeKeyCharacters = function (key) {
|
||||
@ -24,9 +25,9 @@ if (dataIdx === -1) {
|
||||
const deleteData = JSON.parse(process.argv[dataIdx+1]);
|
||||
if (!deleteData.toSign || !deleteData.proof) { return void console.error("Invalid arguments"); }
|
||||
// Check sig
|
||||
const ed = Nacl.util.decodeBase64(deleteData.toSign.edPublic);
|
||||
const signed = Nacl.util.decodeUTF8(JSON.stringify(deleteData.toSign));
|
||||
const proof = Nacl.util.decodeBase64(deleteData.proof);
|
||||
const ed = Util.decodeBase64(deleteData.toSign.edPublic);
|
||||
const signed = Util.decodeUTF8(JSON.stringify(deleteData.toSign));
|
||||
const proof = Util.decodeBase64(deleteData.proof);
|
||||
if (!Nacl.sign.detached.verify(signed, proof, ed)) { return void console.error("Invalid signature"); }
|
||||
edPublic = escapeKeyCharacters(deleteData.toSign.edPublic);
|
||||
}
|
||||
@ -43,7 +44,7 @@ nThen((waitFor) => {
|
||||
pinned = Pins.calculateFromLog(content.toString('utf8'), f);
|
||||
}));
|
||||
}).nThen((waitFor) => {
|
||||
Pins.list(waitFor((err, d) => {
|
||||
Pins.load(waitFor((err, d) => {
|
||||
data = Object.keys(d);
|
||||
}), {
|
||||
exclude: [edPublic + '.ndjson']
|
||||
|
||||
@ -20,7 +20,6 @@ var compare = function () {
|
||||
Pins.list(w(function (err, p) {
|
||||
if (err) { throw err; }
|
||||
list = p;
|
||||
console.log(p);
|
||||
console.log(list);
|
||||
console.log();
|
||||
}), conf);
|
||||
|
||||
@ -34,6 +34,7 @@ Fse.rmSync(oldComponentsPath, { recursive: true, force: true });
|
||||
"mathjax",
|
||||
"open-sans-fontface",
|
||||
"tweetnacl",
|
||||
"tweetnacl-util",
|
||||
"require-css",
|
||||
"requirejs",
|
||||
"requirejs-plugins",
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
const Nacl = require('tweetnacl/nacl-fast');
|
||||
const Util = require('../lib/common-util');
|
||||
|
||||
const keyPair = Nacl.box.keyPair();
|
||||
console.log("You've just generated a new key pair for your support mailbox.");
|
||||
@ -19,9 +20,9 @@ console.log("NOTE: You can change the key pair at any time if you want to revoke
|
||||
console.log();
|
||||
console.log();
|
||||
console.log("Your public key (add it to config.js):");
|
||||
console.log(Nacl.util.encodeBase64(keyPair.publicKey));
|
||||
console.log(Util.encodeBase64(keyPair.publicKey));
|
||||
|
||||
console.log();
|
||||
console.log();
|
||||
console.log("Your private key (store it in a safe place and send it to your instance's admins):");
|
||||
console.log(Nacl.util.encodeBase64(keyPair.secretKey));
|
||||
console.log(Util.encodeBase64(keyPair.secretKey));
|
||||
|
||||
@ -5,13 +5,14 @@
|
||||
let SodiumNative = require('sodium-native');
|
||||
let Nacl = require('tweetnacl/nacl-fast');
|
||||
let LibSodium = require('libsodium-wrappers');
|
||||
let Util = require('../lib/common-util');
|
||||
|
||||
|
||||
let msgStr = "This is a test";
|
||||
let keys = Nacl.sign.keyPair();
|
||||
let pub = keys.publicKey;
|
||||
|
||||
let msg = Nacl.util.decodeUTF8(msgStr);
|
||||
let msg = Util.decodeUTF8(msgStr);
|
||||
let signedMsg = Nacl.sign(msg, keys.secretKey);
|
||||
let sig = signedMsg.subarray(0, 64);
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ var Nacl = require("tweetnacl/nacl-fast");
|
||||
var nThen = require("nthen");
|
||||
var CPNetflux = require("../../www/components/chainpad-netflux/chainpad-netflux");
|
||||
var Hash = require("../../www/common/common-hash");
|
||||
var Util = require("../../lib/common-util");
|
||||
var Rpc = require("../../www/common/rpc");
|
||||
var HK = require("../../lib/hk-util");
|
||||
|
||||
@ -69,7 +70,7 @@ nThen(function (w) {
|
||||
//console.log(i);
|
||||
if (i-- <= 0) { return void done(); }
|
||||
|
||||
var ciphertext = Nacl.util.encodeBase64(Nacl.randomBytes(256));
|
||||
var ciphertext = Util.encodeBase64(Nacl.randomBytes(256));
|
||||
|
||||
client.anonRpc.send('WRITE_PRIVATE_MESSAGE', [
|
||||
client.channel,
|
||||
|
||||
@ -55,16 +55,16 @@ var state = {};
|
||||
var makeCurveKeys = function () {
|
||||
var pair = Nacl.box.keyPair();
|
||||
return {
|
||||
curvePrivate: Nacl.util.encodeBase64(pair.secretKey),
|
||||
curvePublic: Nacl.util.encodeBase64(pair.publicKey),
|
||||
curvePrivate: Util.encodeBase64(pair.secretKey),
|
||||
curvePublic: Util.encodeBase64(pair.publicKey),
|
||||
};
|
||||
};
|
||||
|
||||
var makeEdKeys = function () {
|
||||
var keys = Nacl.sign.keyPair.fromSeed(Nacl.randomBytes(Nacl.sign.seedLength));
|
||||
return {
|
||||
edPrivate: Nacl.util.encodeBase64(keys.secretKey),
|
||||
edPublic: Nacl.util.encodeBase64(keys.publicKey),
|
||||
edPrivate: Util.encodeBase64(keys.secretKey),
|
||||
edPublic: Util.encodeBase64(keys.publicKey),
|
||||
};
|
||||
};
|
||||
|
||||
@ -198,7 +198,7 @@ nThen(function (w) {
|
||||
alice.anonRpc.send('WRITE_PRIVATE_MESSAGE', [
|
||||
alice.mailboxChannel,
|
||||
msg
|
||||
//Nacl.util.encodeBase64(Nacl.randomBytes(128))
|
||||
//Util.encodeBase64(Nacl.randomBytes(128))
|
||||
], w(function (err) {
|
||||
if (err) { throw new Error(err); }
|
||||
console.log('message %s written successfully', i);
|
||||
|
||||
@ -33,7 +33,7 @@ var handler = function (ref, id /* safeKey */, pinned) {
|
||||
//console.log(ref, id);
|
||||
};
|
||||
|
||||
Pins.list(function (err) {
|
||||
Pins.load(function (err) {
|
||||
if (err) { return void console.error(err); }
|
||||
/*
|
||||
for (var id in pinned) {
|
||||
|
||||
@ -43,16 +43,16 @@ process.on('unhandledRejection', function (err) {
|
||||
var makeCurveKeys = function () {
|
||||
var pair = Nacl.box.keyPair();
|
||||
return {
|
||||
curvePrivate: Nacl.util.encodeBase64(pair.secretKey),
|
||||
curvePublic: Nacl.util.encodeBase64(pair.publicKey),
|
||||
curvePrivate: Util.encodeBase64(pair.secretKey),
|
||||
curvePublic: Util.encodeBase64(pair.publicKey),
|
||||
};
|
||||
};
|
||||
|
||||
var makeEdKeys = function () {
|
||||
var keys = Nacl.sign.keyPair.fromSeed(Nacl.randomBytes(Nacl.sign.seedLength));
|
||||
return {
|
||||
edPrivate: Nacl.util.encodeBase64(keys.secretKey),
|
||||
edPublic: Nacl.util.encodeBase64(keys.publicKey),
|
||||
edPrivate: Util.encodeBase64(keys.secretKey),
|
||||
edPublic: Util.encodeBase64(keys.publicKey),
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -9,13 +9,13 @@ var factory = function (Util, Crypto, Keys, Nacl) {
|
||||
var uint8ArrayToHex = Util.uint8ArrayToHex;
|
||||
var hexToBase64 = Util.hexToBase64;
|
||||
var base64ToHex = Util.base64ToHex;
|
||||
Hash.encodeBase64 = Nacl.util.encodeBase64;
|
||||
Hash.decodeBase64 = Nacl.util.decodeBase64;
|
||||
Hash.encodeBase64 = Util.encodeBase64;
|
||||
Hash.decodeBase64 = Util.decodeBase64;
|
||||
|
||||
// This implementation must match that on the server
|
||||
// it's used for a checksum
|
||||
Hash.hashChannelList = function (list) {
|
||||
return Nacl.util.encodeBase64(Nacl.hash(Nacl.util
|
||||
return Util.encodeBase64(Nacl.hash(Util
|
||||
.decodeUTF8(JSON.stringify(list))));
|
||||
};
|
||||
|
||||
@ -34,15 +34,15 @@ var factory = function (Util, Crypto, Keys, Nacl) {
|
||||
|
||||
Hash.getSignPublicFromPrivate = function (edPrivateSafeStr) {
|
||||
var edPrivateStr = Crypto.b64AddSlashes(edPrivateSafeStr);
|
||||
var privateKey = Nacl.util.decodeBase64(edPrivateStr);
|
||||
var privateKey = Util.decodeBase64(edPrivateStr);
|
||||
var keyPair = Nacl.sign.keyPair.fromSecretKey(privateKey);
|
||||
return Nacl.util.encodeBase64(keyPair.publicKey);
|
||||
return Util.encodeBase64(keyPair.publicKey);
|
||||
};
|
||||
Hash.getCurvePublicFromPrivate = function (curvePrivateSafeStr) {
|
||||
var curvePrivateStr = Crypto.b64AddSlashes(curvePrivateSafeStr);
|
||||
var privateKey = Nacl.util.decodeBase64(curvePrivateStr);
|
||||
var privateKey = Util.decodeBase64(curvePrivateStr);
|
||||
var keyPair = Nacl.box.keyPair.fromSecretKey(privateKey);
|
||||
return Nacl.util.encodeBase64(keyPair.publicKey);
|
||||
return Util.encodeBase64(keyPair.publicKey);
|
||||
};
|
||||
|
||||
var getEditHashFromKeys = Hash.getEditHashFromKeys = function (secret) {
|
||||
@ -585,7 +585,7 @@ Version 4: Data URL when not a realtime link yet (new pad or "static" app)
|
||||
secret.channel = base64ToHex(parsed.channel);
|
||||
secret.keys = {
|
||||
fileKeyStr: parsed.key,
|
||||
cryptKey: Nacl.util.decodeBase64(parsed.key)
|
||||
cryptKey: Util.decodeBase64(parsed.key)
|
||||
};
|
||||
} else if (parsed.type === "user") {
|
||||
throw new Error("User hashes can't be opened (yet)");
|
||||
@ -653,15 +653,15 @@ Version 4: Data URL when not a realtime link yet (new pad or "static" app)
|
||||
var keys = secret && secret.keys;
|
||||
var secondary = keys && keys.secondaryKey;
|
||||
if (!secondary) { return; }
|
||||
var curvePair = Nacl.box.keyPair.fromSecretKey(Nacl.util.decodeUTF8(secondary).slice(0,32));
|
||||
var curvePair = Nacl.box.keyPair.fromSecretKey(Util.decodeUTF8(secondary).slice(0,32));
|
||||
var ret = {};
|
||||
ret.form_public = Nacl.util.encodeBase64(curvePair.publicKey);
|
||||
var privateKey = ret.form_private = Nacl.util.encodeBase64(curvePair.secretKey);
|
||||
ret.form_public = Util.encodeBase64(curvePair.publicKey);
|
||||
var privateKey = ret.form_private = Util.encodeBase64(curvePair.secretKey);
|
||||
|
||||
var auditorHash = Hash.getViewHashFromKeys({
|
||||
version: 1,
|
||||
channel: secret.channel,
|
||||
keys: { viewKeyStr: Nacl.util.encodeBase64(keys.cryptKey) }
|
||||
keys: { viewKeyStr: Util.encodeBase64(keys.cryptKey) }
|
||||
});
|
||||
var _parsed = Hash.parseTypeHash('pad', auditorHash);
|
||||
ret.form_auditorHash = _parsed.getHash({auditorKey: privateKey});
|
||||
@ -720,12 +720,12 @@ Version 4: Data URL when not a realtime link yet (new pad or "static" app)
|
||||
|
||||
Hash.decodeDataOptions = function (opts) {
|
||||
var b64 = decodeURIComponent(opts);
|
||||
var str = Nacl.util.encodeUTF8(Nacl.util.decodeBase64(b64));
|
||||
var str = Util.encodeUTF8(Util.decodeBase64(b64));
|
||||
return Util.tryParse(str) || {};
|
||||
};
|
||||
Hash.encodeDataOptions = function (opts) {
|
||||
var str = JSON.stringify(opts);
|
||||
var b64 = Nacl.util.encodeBase64(Nacl.util.decodeUTF8(str));
|
||||
var b64 = Util.encodeBase64(Util.decodeUTF8(str));
|
||||
return encodeURIComponent(b64);
|
||||
};
|
||||
Hash.getNewPadURL = function (href, opts) {
|
||||
|
||||
@ -3,12 +3,22 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
(function (window) {
|
||||
var Util = {};
|
||||
const factory = (NaclUtil) => {
|
||||
var Util = window.CryptPad_Util = {};
|
||||
|
||||
// polyfill for atob in case you're using this from node...
|
||||
window.atob = window.atob || function (str) { return Buffer.from(str, 'base64').toString('binary'); };
|
||||
window.btoa = window.btoa || function (str) { return Buffer.from(str, 'binary').toString('base64'); };
|
||||
|
||||
Util.encodeBase64 = NaclUtil.encodeBase64;
|
||||
Util.decodeBase64 = str => {
|
||||
let i = str.length % 4;
|
||||
if (i) { str += '='.repeat(4-i); }
|
||||
return NaclUtil.decodeBase64(str);
|
||||
};
|
||||
Util.encodeUTF8 = NaclUtil.encodeUTF8;
|
||||
Util.decodeUTF8 = NaclUtil.decodeUTF8;
|
||||
|
||||
Util.slice = function (A, start, end) {
|
||||
return Array.prototype.slice.call(A, start, end);
|
||||
};
|
||||
@ -857,14 +867,16 @@
|
||||
};
|
||||
/* End of code copied from saferphore */
|
||||
|
||||
return Util;
|
||||
};
|
||||
|
||||
if (typeof(module) !== 'undefined' && module.exports) {
|
||||
module.exports = Util;
|
||||
module.exports = factory(require('tweetnacl-util'));
|
||||
} else if ((typeof(define) !== 'undefined' && define !== null) && (define.amd !== null)) {
|
||||
define([], function () {
|
||||
window.CryptPad_Util = Util;
|
||||
return Util;
|
||||
define(['/components/tweetnacl-util/nacl-util.min.js'], function () {
|
||||
return factory(globalThis?.nacl?.util);
|
||||
});
|
||||
} else {
|
||||
window.CryptPad_Util = Util;
|
||||
// Unsupported initialization
|
||||
}
|
||||
}(typeof(self) !== 'undefined'? self: this));
|
||||
|
||||
@ -26,7 +26,7 @@ const factory = (nThen, Util, ApiConfig = {}, Nacl) => {
|
||||
};
|
||||
|
||||
var clone = o => JSON.parse(JSON.stringify(o));
|
||||
var randomToken = () => Nacl.util.encodeBase64(Nacl.randomBytes(24));
|
||||
var randomToken = () => Util.encodeBase64(Nacl.randomBytes(24));
|
||||
var postData = function (url, data, cb) {
|
||||
var CB = Util.once(Util.mkAsync(cb));
|
||||
fetch(url, {
|
||||
@ -53,7 +53,7 @@ const factory = (nThen, Util, ApiConfig = {}, Nacl) => {
|
||||
|
||||
var serverCommand = function (keypair, my_data, cb) {
|
||||
var obj = clone(my_data);
|
||||
obj.publicKey = Nacl.util.encodeBase64(keypair.publicKey);
|
||||
obj.publicKey = Util.encodeBase64(keypair.publicKey);
|
||||
obj.nonce = randomToken();
|
||||
var href = new URL('/api/auth/', API_ORIGIN);
|
||||
var txid, date;
|
||||
@ -82,9 +82,9 @@ const factory = (nThen, Util, ApiConfig = {}, Nacl) => {
|
||||
var copy = clone(obj);
|
||||
copy.txid = txid;
|
||||
copy.date = date;
|
||||
var toSign = Nacl.util.decodeUTF8(JSON.stringify(copy));
|
||||
var toSign = Util.decodeUTF8(JSON.stringify(copy));
|
||||
var sig = Nacl.sign.detached(toSign, keypair.secretKey);
|
||||
var encoded = Nacl.util.encodeBase64(sig);
|
||||
var encoded = Util.encodeBase64(sig);
|
||||
var obj2 = {
|
||||
sig: encoded,
|
||||
txid: txid,
|
||||
|
||||
@ -23,7 +23,7 @@ const factory = (Util, ApiConfig = {}, ServerCommand, Nacl) => {
|
||||
// [b64_public, b64_sig, b64_block [version, nonce, content]]
|
||||
|
||||
Block.seed = function () {
|
||||
return Nacl.hash(Nacl.util.decodeUTF8('pewpewpew'));
|
||||
return Nacl.hash(Util.decodeUTF8('pewpewpew'));
|
||||
};
|
||||
|
||||
// should be deterministic from a seed...
|
||||
@ -49,8 +49,8 @@ const factory = (Util, ApiConfig = {}, ServerCommand, Nacl) => {
|
||||
try {
|
||||
var sign = keys.sign;
|
||||
return {
|
||||
edPrivate: Nacl.util.encodeBase64(sign.secretKey),
|
||||
edPublic: Nacl.util.encodeBase64(sign.publicKey),
|
||||
edPrivate: Util.encodeBase64(sign.secretKey),
|
||||
edPublic: Util.encodeBase64(sign.publicKey),
|
||||
};
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
@ -60,7 +60,7 @@ const factory = (Util, ApiConfig = {}, ServerCommand, Nacl) => {
|
||||
|
||||
// (UTF8 content, keys object) => Uint8Array block
|
||||
Block.encrypt = function (version, content, keys) {
|
||||
var u8 = Nacl.util.decodeUTF8(content);
|
||||
var u8 = Util.decodeUTF8(content);
|
||||
var nonce = Nacl.randomBytes(Nacl.secretbox.nonceLength);
|
||||
return Block.join([
|
||||
[0],
|
||||
@ -77,7 +77,7 @@ const factory = (Util, ApiConfig = {}, ServerCommand, Nacl) => {
|
||||
|
||||
var plaintext = Nacl.secretbox.open(box, nonce, keys.symmetric);
|
||||
try {
|
||||
return JSON.parse(Nacl.util.encodeUTF8(plaintext));
|
||||
return JSON.parse(Util.encodeUTF8(plaintext));
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return;
|
||||
@ -98,9 +98,9 @@ const factory = (Util, ApiConfig = {}, ServerCommand, Nacl) => {
|
||||
|
||||
// serialize {publickey, sig, ciphertext}
|
||||
return {
|
||||
publicKey: Nacl.util.encodeBase64(keys.sign.publicKey),
|
||||
signature: Nacl.util.encodeBase64(sig),
|
||||
ciphertext: Nacl.util.encodeBase64(ciphertext),
|
||||
publicKey: Util.encodeBase64(keys.sign.publicKey),
|
||||
signature: Util.encodeBase64(sig),
|
||||
ciphertext: Util.encodeBase64(ciphertext),
|
||||
};
|
||||
};
|
||||
|
||||
@ -111,14 +111,14 @@ const factory = (Util, ApiConfig = {}, ServerCommand, Nacl) => {
|
||||
// sign your old publicKey with your old privateKey
|
||||
var u8_sig = Nacl.sign.detached(u8_pub, u8_secret);
|
||||
// return an array with the sig and the pubkey
|
||||
return JSON.stringify([u8_pub, u8_sig].map(Nacl.util.encodeBase64));
|
||||
return JSON.stringify([u8_pub, u8_sig].map(Util.encodeBase64));
|
||||
} catch (err) {
|
||||
return void console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
var urlSafeB64 = function (u8) {
|
||||
return Nacl.util.encodeBase64(u8).replace(/\//g, '-');
|
||||
return Util.encodeBase64(u8).replace(/\//g, '-');
|
||||
};
|
||||
|
||||
Block.getBlockUrl = function (keys) {
|
||||
@ -138,7 +138,7 @@ const factory = (Util, ApiConfig = {}, ServerCommand, Nacl) => {
|
||||
|
||||
var decodeSafeB64 = function (b64) {
|
||||
try {
|
||||
return Nacl.util.decodeBase64(b64.replace(/\-/g, '/'));
|
||||
return Util.decodeBase64(b64.replace(/\-/g, '/'));
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return;
|
||||
|
||||
@ -4,8 +4,10 @@
|
||||
|
||||
(() => {
|
||||
const factory = () => {
|
||||
const version = 8;
|
||||
return {
|
||||
currentVersion: 'v7'
|
||||
currentVersionNumber: version,
|
||||
currentVersion: 'v' + version
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ const factory = (AppConfig = {}, ApiConfig = {},
|
||||
setCustomize({AppConfig,ApiConfig});
|
||||
}
|
||||
|
||||
const Types = { setCustomize };
|
||||
const Types = { OO_APPS, setCustomize };
|
||||
|
||||
Types.__defineGetter__("availableTypes", function () {
|
||||
if (ApiConfig.appsToDisable) {
|
||||
|
||||
@ -14,8 +14,8 @@ var factory = function (Util, Nacl) {
|
||||
// we will sign various message with our edPrivate keys
|
||||
// this handles that in a generic way
|
||||
var signMsg = function (data, signKey) {
|
||||
var buffer = Nacl.util.decodeUTF8(JSON.stringify(data));
|
||||
return Nacl.util.encodeBase64(Nacl.sign.detached(buffer, signKey));
|
||||
var buffer = Util.decodeUTF8(JSON.stringify(data));
|
||||
return Util.encodeBase64(Nacl.sign.detached(buffer, signKey));
|
||||
};
|
||||
|
||||
// sendMsg takes a pre-formed message, does a little validation
|
||||
@ -299,7 +299,7 @@ var factory = function (Util, Nacl) {
|
||||
var signKey;
|
||||
|
||||
try {
|
||||
signKey = Nacl.util.decodeBase64(edPrivateKey);
|
||||
signKey = Util.decodeBase64(edPrivateKey);
|
||||
if (signKey.length !== 64) {
|
||||
throw new Error('private key did not match expected length of 64');
|
||||
}
|
||||
@ -308,7 +308,7 @@ var factory = function (Util, Nacl) {
|
||||
}
|
||||
|
||||
try {
|
||||
if (Nacl.util.decodeBase64(edPublicKey).length !== 32) {
|
||||
if (Util.decodeBase64(edPublicKey).length !== 32) {
|
||||
return void cb('expected public key to be 32 uint');
|
||||
}
|
||||
} catch (err) { return void cb(err); }
|
||||
|
||||
1
src/tweetnacl/.gitignore
vendored
1
src/tweetnacl/.gitignore
vendored
@ -1 +0,0 @@
|
||||
node_modules
|
||||
@ -1,3 +0,0 @@
|
||||
test
|
||||
.travis.yml
|
||||
bower.json
|
||||
@ -1,7 +0,0 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.10"
|
||||
env:
|
||||
- NACL_SRC=nacl.min.js
|
||||
- NACL_SRC=nacl-fast.min.js
|
||||
script: "npm run testall"
|
||||
@ -1,101 +0,0 @@
|
||||
TweetNaCl.js Changelog
|
||||
======================
|
||||
|
||||
|
||||
v0.12.2
|
||||
-------
|
||||
|
||||
* Improved performance of curve operations, making `nacl.scalarMult`, `nacl.box`,
|
||||
`nacl.sign` and related functions up to 3x faster in `nacl-fast` version.
|
||||
|
||||
|
||||
v0.12.1
|
||||
-------
|
||||
|
||||
* Significantly improved performance of Salsa20 (~1.5x faster) and
|
||||
Poly1305 (~3.5x faster) in `nacl-fast` version.
|
||||
|
||||
|
||||
v0.12.0
|
||||
-------
|
||||
|
||||
* Instead of using the given secret key directly, TweetNaCl.js now copies it to
|
||||
a new array in `nacl.box.keyPair.fromSecretKey` and
|
||||
`nacl.sign.keyPair.fromSecretKey`.
|
||||
|
||||
|
||||
v0.11.2
|
||||
-------
|
||||
|
||||
* Added new constant: `nacl.sign.seedLength`.
|
||||
|
||||
|
||||
v0.11.1
|
||||
-------
|
||||
|
||||
* Even faster hash for both short and long inputs (in `nacl-fast`).
|
||||
|
||||
|
||||
v0.11.0
|
||||
-------
|
||||
|
||||
* Implement `nacl.sign.keyPair.fromSeed` to enable creation of sign key pairs
|
||||
deterministically from a 32-byte seed. (It behaves like
|
||||
[libsodium's](http://doc.libsodium.org/public-key_cryptography/public-key_signatures.html)
|
||||
`crypto_sign_seed_keypair`: the seed becomes a secret part of the secret key.)
|
||||
|
||||
* Fast version now has an improved hash implementation that is 2x-5x faster.
|
||||
|
||||
* Fixed benchmarks, which may have produced incorrect measurements.
|
||||
|
||||
|
||||
v0.10.1
|
||||
-------
|
||||
|
||||
* Exported undocumented `nacl.lowlevel.crypto_core_hsalsa20`.
|
||||
|
||||
|
||||
v0.10.0
|
||||
-------
|
||||
|
||||
* **Signature API breaking change!** `nacl.sign` and `nacl.sign.open` now deal
|
||||
with signed messages, and new `nacl.sign.detached` and
|
||||
`nacl.sign.detached.verify` are available.
|
||||
|
||||
Previously, `nacl.sign` returned a signature, and `nacl.sign.open` accepted a
|
||||
message and "detached" signature. This was unlike NaCl's API, which dealt with
|
||||
signed messages (concatenation of signature and message).
|
||||
|
||||
The new API is:
|
||||
|
||||
nacl.sign(message, secretKey) -> signedMessage
|
||||
nacl.sign.open(signedMessage, publicKey) -> message | null
|
||||
|
||||
Since detached signatures are common, two new API functions were introduced:
|
||||
|
||||
nacl.sign.detached(message, secretKey) -> signature
|
||||
nacl.sign.detached.verify(message, signature, publicKey) -> true | false
|
||||
|
||||
(Note that it's `verify`, not `open`, and it returns a boolean value, unlike
|
||||
`open`, which returns an "unsigned" message.)
|
||||
|
||||
* NPM package now comes without `test` directory to keep it small.
|
||||
|
||||
|
||||
v0.9.2
|
||||
------
|
||||
|
||||
* Improved documentation.
|
||||
* Fast version: increased theoretical message size limit from 2^32-1 to 2^52
|
||||
bytes in Poly1305 (and thus, secretbox and box). However this has no impact
|
||||
in practice since JavaScript arrays or ArrayBuffers are limited to 32-bit
|
||||
indexes, and most implementations won't allocate more than a gigabyte or so.
|
||||
(Obviously, there are no tests for the correctness of implementation.) Also,
|
||||
it's not recommended to use messages that large without splitting them into
|
||||
smaller packets anyway.
|
||||
|
||||
|
||||
v0.9.1
|
||||
------
|
||||
|
||||
* Initial release
|
||||
@ -1,455 +0,0 @@
|
||||
TweetNaCl.js
|
||||
============
|
||||
|
||||
Port of [TweetNaCl](http://tweetnacl.cr.yp.to) / [NaCl](http://nacl.cr.yp.to/)
|
||||
to JavaScript for modern browsers and Node.js. Public domain.
|
||||
|
||||
[
|
||||
](https://travis-ci.org/dchest/tweetnacl-js)
|
||||
|
||||
[Demo](https://dchest.github.io/tweetnacl-js/)
|
||||
|
||||
**:warning: Beta version. The library is stable and API is frozen, however
|
||||
it has not been independently reviewed. If you can help reviewing it, please
|
||||
[contact me](mailto:dmitry@codingrobots.com).**
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
* [Overview](#overview)
|
||||
* [Installation](#installation)
|
||||
* [Usage](#usage)
|
||||
* [Public-key authenticated encryption (box)](#public-key-authenticated-encryption-box)
|
||||
* [Secret-key authenticated encryption (secretbox)](#secret-key-authenticated-encryption-secretbox)
|
||||
* [Scalar multiplication](#scalar-multiplication)
|
||||
* [Signatures](#signatures)
|
||||
* [Hashing](#hashing)
|
||||
* [Random bytes generation](#random-bytes-generation)
|
||||
* [Constant-time comparison](#constant-time-comparison)
|
||||
* [Utilities](#utilities)
|
||||
* [Examples](#examples)
|
||||
* [System requirements](#system-requirements)
|
||||
* [Development and testing](#development-and-testing)
|
||||
* [Contributors](#contributors)
|
||||
* [Who uses it](#who-uses-it)
|
||||
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The primary goal of this project is to produce a translation of TweetNaCl to
|
||||
JavaScript which is as close as possible to the original C implementation, plus
|
||||
a thin layer of idiomatic high-level API on top of it.
|
||||
|
||||
There are two versions, you can use either of them:
|
||||
|
||||
* `nacl.js` is the port of TweetNaCl with minimum differences from the
|
||||
original + high-level API.
|
||||
|
||||
* `nacl-fast.js` is like `nacl.js`, but with some functions replaced with
|
||||
faster versions.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
You can install TweetNaCl.is via a package manager:
|
||||
|
||||
[Bower](http://bower.io):
|
||||
|
||||
$ bower install tweetnacl
|
||||
|
||||
[NPM](https://www.npmjs.org/):
|
||||
|
||||
$ npm install tweetnacl
|
||||
|
||||
or [download source code](https://github.com/dchest/tweetnacl-js/releases).
|
||||
|
||||
|
||||
Usage
|
||||
------
|
||||
|
||||
All API functions accept and return bytes as `Uint8Array`s. If you need to
|
||||
encode or decode strings, use functions from `nacl.util` namespace.
|
||||
|
||||
### Public-key authenticated encryption (box)
|
||||
|
||||
Implements *curve25519-xsalsa20-poly1305*.
|
||||
|
||||
#### nacl.box.keyPair()
|
||||
|
||||
Generates a new random key pair for box and returns it as an object with
|
||||
`publicKey` and `secretKey` members:
|
||||
|
||||
{
|
||||
publicKey: ..., // Uint8Array with 32-byte public key
|
||||
secretKey: ... // Uint8Array with 32-byte secret key
|
||||
}
|
||||
|
||||
|
||||
#### nacl.box.keyPair.fromSecretKey(secretKey)
|
||||
|
||||
Returns a key pair for box with public key corresponding to the given secret
|
||||
key.
|
||||
|
||||
#### nacl.box(message, nonce, theirPublicKey, mySecretKey)
|
||||
|
||||
Encrypt and authenticates message using peer's public key, our secret key, and
|
||||
the given nonce, which must be unique for each distinct message for a key pair.
|
||||
|
||||
Returns an encrypted and authenticated message, which is
|
||||
`nacl.box.overheadLength` longer than the original message.
|
||||
|
||||
#### nacl.box.open(box, nonce, theirPublicKey, mySecretKey)
|
||||
|
||||
Authenticates and decrypts the given box with peer's public key, our secret
|
||||
key, and the given nonce.
|
||||
|
||||
Returns the original message, or `false` if authentication fails.
|
||||
|
||||
#### nacl.box.before(theirPublicKey, mySecretKey)
|
||||
|
||||
Returns a precomputed shared key which can be used in `nacl.box.after` and
|
||||
`nacl.box.open.after`.
|
||||
|
||||
#### nacl.box.after(message, nonce, sharedKey)
|
||||
|
||||
Same as `nacl.box`, but uses a shared key precomputed with `nacl.box.before`.
|
||||
|
||||
#### nacl.box.open.after(box, nonce, sharedKey)
|
||||
|
||||
Same as `nacl.box.open`, but uses a shared key precomputed with `nacl.box.before`.
|
||||
|
||||
#### nacl.box.publicKeyLength = 32
|
||||
|
||||
Length of public key in bytes.
|
||||
|
||||
#### nacl.box.secretKeyLength = 32
|
||||
|
||||
Length of secret key in bytes.
|
||||
|
||||
#### nacl.box.sharedKeyLength = 32
|
||||
|
||||
Length of precomputed shared key in bytes.
|
||||
|
||||
#### nacl.box.nonceLength = 24
|
||||
|
||||
Length of nonce in bytes.
|
||||
|
||||
#### nacl.box.overheadLength = 16
|
||||
|
||||
Length of overhead added to box compared to original message.
|
||||
|
||||
|
||||
### Secret-key authenticated encryption (secretbox)
|
||||
|
||||
Implements *xsalsa20-poly1305*.
|
||||
|
||||
#### nacl.secretbox(message, nonce, key)
|
||||
|
||||
Encrypt and authenticates message using the key and the nonce. The nonce must
|
||||
be unique for each distinct message for this key.
|
||||
|
||||
Returns an encrypted and authenticated message, which is
|
||||
`nacl.secretbox.overheadLength` longer than the original message.
|
||||
|
||||
#### nacl.secretbox.open(box, nonce, key)
|
||||
|
||||
Authenticates and decrypts the given secret box using the key and the nonce.
|
||||
|
||||
Returns the original message, or `false` if authentication fails.
|
||||
|
||||
#### nacl.secretbox.keyLength = 32
|
||||
|
||||
Length of key in bytes.
|
||||
|
||||
#### nacl.secretbox.nonceLength = 24
|
||||
|
||||
Length of nonce in bytes.
|
||||
|
||||
#### nacl.secretbox.overheadLength = 16
|
||||
|
||||
Length of overhead added to secret box compared to original message.
|
||||
|
||||
|
||||
### Scalar multiplication
|
||||
|
||||
Implements *curve25519*.
|
||||
|
||||
#### nacl.scalarMult(n, p)
|
||||
|
||||
Multiplies an integer `n` by a group element `p` and returns the resulting
|
||||
group element.
|
||||
|
||||
#### nacl.scalarMult.base(n)
|
||||
|
||||
Multiplies an integer `n` by a standard group element and returns the resulting
|
||||
group element.
|
||||
|
||||
#### nacl.scalarMult.scalarLength = 32
|
||||
|
||||
Length of scalar in bytes.
|
||||
|
||||
#### nacl.scalarMult.groupElementLength = 32
|
||||
|
||||
Length of group element in bytes.
|
||||
|
||||
|
||||
### Signatures
|
||||
|
||||
Implements [ed25519](http://ed25519.cr.yp.to).
|
||||
|
||||
#### nacl.sign.keyPair()
|
||||
|
||||
Generates new random key pair for signing and returns it as an object with
|
||||
`publicKey` and `secretKey` members:
|
||||
|
||||
{
|
||||
publicKey: ..., // Uint8Array with 32-byte public key
|
||||
secretKey: ... // Uint8Array with 64-byte secret key
|
||||
}
|
||||
|
||||
#### nacl.sign.keyPair.fromSecretKey(secretKey)
|
||||
|
||||
Returns a signing key pair with public key corresponding to the given
|
||||
64-byte secret key. The secret key must have been generated by
|
||||
`nacl.sign.keyPair` or `nacl.sign.keyPair.fromSeed`.
|
||||
|
||||
#### nacl.sign.keyPair.fromSeed(seed)
|
||||
|
||||
Returns a new signing key pair generated deterministically from a 32-byte seed.
|
||||
The seed must contain enough entropy to be secure. This method is not
|
||||
recommended for general use: instead, use `nacl.sign.keyPair` to generate a new
|
||||
key pair from a random seed.
|
||||
|
||||
#### nacl.sign(message, secretKey)
|
||||
|
||||
Signs the message using the secret key and returns a signed message.
|
||||
|
||||
#### nacl.sign.open(signedMessage, publicKey)
|
||||
|
||||
Verifies the signed message and returns the message without signature.
|
||||
|
||||
Returns `null` if verification failed.
|
||||
|
||||
#### nacl.sign.detached(message, secretKey)
|
||||
|
||||
Signs the message using the secret key and returns a signature.
|
||||
|
||||
#### nacl.sign.detached.verify(message, signature, publicKey)
|
||||
|
||||
Verifies the signature for the message and returns `true` if verification
|
||||
succeeded or `false` if it failed.
|
||||
|
||||
#### nacl.sign.publicKeyLength = 32
|
||||
|
||||
Length of signing public key in bytes.
|
||||
|
||||
#### nacl.sign.secretKeyLength = 64
|
||||
|
||||
Length of signing secret key in bytes.
|
||||
|
||||
#### nacl.sign.seedLength = 32
|
||||
|
||||
Length of seed for `nacl.sign.keyPair.fromSeed` in bytes.
|
||||
|
||||
#### nacl.sign.signatureLength = 64
|
||||
|
||||
Length of signature in bytes.
|
||||
|
||||
|
||||
### Hashing
|
||||
|
||||
Implements *SHA-512*.
|
||||
|
||||
#### nacl.hash(message)
|
||||
|
||||
Returns SHA-512 hash of the message.
|
||||
|
||||
#### nacl.hash.hashLength = 64
|
||||
|
||||
Length of hash in bytes.
|
||||
|
||||
|
||||
### Random bytes generation
|
||||
|
||||
#### nacl.randomBytes(length)
|
||||
|
||||
Returns a `Uint8Array` of the given length containing random bytes of
|
||||
cryptographic quality.
|
||||
|
||||
**Implementation note**
|
||||
|
||||
TweetNaCl.js uses the following methods to generate random bytes,
|
||||
depending on the platform it runs on:
|
||||
|
||||
* `window.crypto.getRandomValues` (WebCrypto standard)
|
||||
* `window.msCrypto.getRandomValues` (Internet Explorer 11)
|
||||
* `crypto.randomBytes` (Node.js)
|
||||
|
||||
Note that browsers are required to throw `QuotaExceededError` exception if
|
||||
requested `length` is more than 65536, so do not ask for more than 65536 bytes
|
||||
in *one call* (multiple calls to get as many bytes as you like are okay:
|
||||
browsers can generate infinite amount of random bytes without any bad
|
||||
consequences).
|
||||
|
||||
If the platform doesn't provide a suitable PRNG, the following functions,
|
||||
which require random numbers, will throw exception:
|
||||
|
||||
* `nacl.randomBytes`
|
||||
* `nacl.box.keyPair`
|
||||
* `nacl.sign.keyPair`
|
||||
|
||||
Other functions are deterministic and will continue working.
|
||||
|
||||
If a platform you are targeting doesn't implement secure random number
|
||||
generator, but you somehow have a cryptographically-strong source of entropy
|
||||
(not `Math.random`!), and you know what you are doing, you can plug it into
|
||||
TweetNaCl.js like this:
|
||||
|
||||
nacl.setPRNG(function(x, n) {
|
||||
// ... copy n random bytes into x ...
|
||||
});
|
||||
|
||||
Note that `nacl.setPRNG` *completely replaces* internal random byte generator
|
||||
with the one provided.
|
||||
|
||||
|
||||
### Constant-time comparison
|
||||
|
||||
#### nacl.verify(x, y)
|
||||
|
||||
Compares `x` and `y` in constant time and returns `true` if their lengths are
|
||||
non-zero and equal, and their contents are equal.
|
||||
|
||||
Returns `false` if either of the arguments has zero length, or arguments have
|
||||
different lengths, or their contents differ.
|
||||
|
||||
|
||||
### Utilities
|
||||
|
||||
Encoding/decoding functions are provided for convenience. They are correct,
|
||||
however their performance and wide compatibility with uncommon runtimes is not
|
||||
something that is considered important compared to the simplicity and size of
|
||||
implementation. You can use third-party libraries if you need to.
|
||||
|
||||
#### nacl.util.decodeUTF8(string)
|
||||
|
||||
Decodes string and returns `Uint8Array` of bytes.
|
||||
|
||||
#### nacl.util.encodeUTF8(array)
|
||||
|
||||
Encodes `Uint8Array` or `Array` of bytes into string.
|
||||
|
||||
#### nacl.util.decodeBase64(string)
|
||||
|
||||
Decodes Base-64 encoded string and returns `Uint8Array` of bytes.
|
||||
|
||||
#### nacl.util.encodeBase64(array)
|
||||
|
||||
Encodes `Uint8Array` or `Array` of bytes into string using Base-64 encoding.
|
||||
|
||||
|
||||
System requirements
|
||||
-------------------
|
||||
|
||||
TweetNaCl.js supports modern browsers that have a cryptographically secure
|
||||
pseudorandom number generator and typed arrays, including the latest versions
|
||||
of:
|
||||
|
||||
* Chrome
|
||||
* Firefox
|
||||
* Safari (Mac, iOS)
|
||||
* Internet Explorer 11
|
||||
|
||||
Other systems:
|
||||
|
||||
* Node.js (we test on 0.10 and later)
|
||||
|
||||
|
||||
Development and testing
|
||||
------------------------
|
||||
|
||||
Install NPM modules needed for development:
|
||||
|
||||
$ npm install
|
||||
|
||||
To build minified versions:
|
||||
|
||||
$ npm run build
|
||||
|
||||
Tests use minified version, so make sure to rebuild it every time you change
|
||||
`nacl.js` or `nacl-fast.js`.
|
||||
|
||||
### Testing
|
||||
|
||||
To run tests in Node.js:
|
||||
|
||||
$ npm test
|
||||
|
||||
By default all tests described here work on `nacl.min.js`. To test other
|
||||
versions, set environment variable `NACL_SRC` to the file name you want to test.
|
||||
For example, the following command will test fast minified version:
|
||||
|
||||
$ NACL_SRC=nacl-fast.min.js npm test
|
||||
|
||||
To run full suite of tests in Node.hs, including comparing outputs of
|
||||
JavaScript port to outputs of the original C version:
|
||||
|
||||
$ npm run testall
|
||||
|
||||
To prepare tests for browsers:
|
||||
|
||||
$ npm run browser
|
||||
|
||||
and then open `tests/browser/test.html` (or `tests/browser/test-fast.html`) to
|
||||
run them.
|
||||
|
||||
To run headless browser tests with `testling`:
|
||||
|
||||
$ npm run testling
|
||||
|
||||
(If you get `Error: spawn ENOENT`, install *xvfb*: `sudo apt-get install xvfb`.)
|
||||
|
||||
### Benchmarking
|
||||
|
||||
To run benchmarks in Node.js:
|
||||
|
||||
$ npm run bench
|
||||
$ NACL_SRC=nacl-fast.min.js npm run bench
|
||||
|
||||
To run benchmarks in a browser, open `test/benchmark/bench.html` (or
|
||||
`test/benchmark/bench-fast.html`).
|
||||
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
JavaScript port:
|
||||
|
||||
* [Dmitry Chestnykh](http://github.com/dchest) (ported xsalsa20, poly1305, curve25519)
|
||||
* [Devi Mandiri](https://github.com/devi) (ported curve25519, ed25519, sha512)
|
||||
|
||||
Original authors of [NaCl](http://nacl.cr.yp.to), [TweetNaCl](http://tweetnacl.cr.yp.to)
|
||||
and [Poly1305-donna](https://github.com/floodyberry/poly1305-donna)
|
||||
(who are *not* responsible for any errors in this implementation):
|
||||
|
||||
* [Daniel J. Bernstein](http://cr.yp.to/djb.html)
|
||||
* Wesley Janssen
|
||||
* [Tanja Lange](http://hyperelliptic.org/tanja)
|
||||
* [Peter Schwabe](http://www.cryptojedi.org/users/peter/)
|
||||
* [Matthew Dempsky](https://github.com/mdempsky)
|
||||
* [Andrew Moon](https://github.com/floodyberry)
|
||||
|
||||
Contributors have dedicated their work to the public domain.
|
||||
|
||||
This software is distributed without any warranty.
|
||||
|
||||
|
||||
Who uses it
|
||||
-----------
|
||||
|
||||
Some notable users of TweetNaCl.js:
|
||||
|
||||
* [miniLock](http://minilock.io/)
|
||||
* [Stellar](https://www.stellar.org/)
|
||||
@ -1,36 +0,0 @@
|
||||
{
|
||||
"name": "tweetnacl",
|
||||
"version": "0.12.2",
|
||||
"homepage": "https://dchest.github.io/tweetnacl-js",
|
||||
"authors": [
|
||||
"TweetNaCl.js Contributors"
|
||||
],
|
||||
"description": "Port of TweetNaCl cryptographic library to JavaScript",
|
||||
"main": "nacl.js",
|
||||
"moduleType": [
|
||||
"globals",
|
||||
"node"
|
||||
],
|
||||
"keywords": [
|
||||
"crypto",
|
||||
"cryptography",
|
||||
"curve25519",
|
||||
"ed25519",
|
||||
"encrypt",
|
||||
"hash",
|
||||
"key",
|
||||
"nacl",
|
||||
"poly1305",
|
||||
"public",
|
||||
"salsa20",
|
||||
"signatures"
|
||||
],
|
||||
"license": "Public domain",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"package.json"
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
2
src/tweetnacl/nacl-fast.min.js
vendored
2
src/tweetnacl/nacl-fast.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
1
src/tweetnacl/nacl.min.js
vendored
1
src/tweetnacl/nacl.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,57 +0,0 @@
|
||||
{
|
||||
"name": "tweetnacl",
|
||||
"version": "0.12.2",
|
||||
"description": "Port of TweetNaCl cryptographic library to JavaScript",
|
||||
"main": "nacl.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "uglifyjs nacl.js -c -m -o nacl.min.js && uglifyjs nacl-fast.js -c -m -o nacl-fast.min.js",
|
||||
"test": "tape test/*.js | faucet",
|
||||
"testall": "make -C test/c && tape test/*.js test/c/*.js | faucet",
|
||||
"browser": "browserify test/browser/init.js test/*.js | uglifyjs -c -m -o test/browser/_bundle.js 2>/dev/null",
|
||||
"browser-quick": "browserify test/browser/init.js test/*.quick.js | uglifyjs -c -m -o test/browser/_bundle-quick.js 2>/dev/null",
|
||||
"testling": "browserify test/browser/testling_init.js test/*.js | testling | faucet",
|
||||
"firefox": "browserify test/browser/testling_init.js test/*.js | testling -x firefox | faucet",
|
||||
"chrome": "browserify test/browser/testling_init.js test/*.js | testling -x google-chrome | faucet",
|
||||
"bench": "node test/benchmark/bench.js"
|
||||
},
|
||||
"testling": {
|
||||
"files": "test/*.js",
|
||||
"browsers": [
|
||||
"ie/11..latest",
|
||||
"chrome/22..latest",
|
||||
"firefox/16..latest",
|
||||
"safari/latest",
|
||||
"opera/11.0..latest",
|
||||
"iphone/6..latest",
|
||||
"ipad/6..latest",
|
||||
"android-browser/latest"
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dchest/tweetnacl-js.git"
|
||||
},
|
||||
"keywords": [
|
||||
"crypto",
|
||||
"cryptography",
|
||||
"curve25519",
|
||||
"ed25519",
|
||||
"encrypt",
|
||||
"hash",
|
||||
"key",
|
||||
"nacl",
|
||||
"poly1305",
|
||||
"public",
|
||||
"salsa20",
|
||||
"signatures"
|
||||
],
|
||||
"author": "TweetNaCl-js contributors",
|
||||
"license": "Public domain",
|
||||
"bugs": {
|
||||
"url": "https://github.com/dchest/tweetnacl-js/issues"
|
||||
},
|
||||
"homepage": "https://dchest.github.io/tweetnacl-js"
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
var b64Vectors = require('./data/base64.random');
|
||||
|
||||
test('nacl.util.encodeBase64 random test vectors', function(t) {
|
||||
b64Vectors.forEach(function(vec) {
|
||||
var b = new Uint8Array(vec[0]);
|
||||
var s = vec[1];
|
||||
t.equal(nacl.util.encodeBase64(b), s);
|
||||
t.deepEqual(nacl.util.decodeBase64(s), b);
|
||||
});
|
||||
t.end();
|
||||
});
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
var testBytes = new Uint8Array([208,159,209,128,208,184,208,178,208,181,209,130,44,32,78,97,67,108]);
|
||||
var utf8String = "Привет, NaCl";
|
||||
var b64String = "0J/RgNC40LLQtdGCLCBOYUNs";
|
||||
|
||||
test('nacl.util.decodeUTF8', function(t) {
|
||||
t.plan(1);
|
||||
t.deepEqual(nacl.util.decodeUTF8(utf8String), testBytes);
|
||||
});
|
||||
|
||||
test('nacl.util.encodeUTF8', function(t) {
|
||||
t.plan(1);
|
||||
t.equal(nacl.util.encodeUTF8(testBytes), utf8String);
|
||||
});
|
||||
|
||||
test('nacl.util.decodeBase64', function(t) {
|
||||
t.plan(1);
|
||||
t.deepEqual(nacl.util.decodeBase64(b64String), testBytes);
|
||||
});
|
||||
|
||||
test('nacl.util.encodeBase64', function(t) {
|
||||
t.plan(1);
|
||||
t.equal(nacl.util.encodeBase64(testBytes), b64String);
|
||||
});
|
||||
@ -1,16 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
test('nacl.verify', function(t) {
|
||||
t.ok(nacl.verify(new Uint8Array(1), new Uint8Array(1)), 'equal arrays of length 1 should verify');
|
||||
t.ok(nacl.verify(new Uint8Array(1000), new Uint8Array(1000)), 'equal arrays of length 1000 should verify');
|
||||
var a = new Uint8Array(764), b = new Uint8Array(764);
|
||||
for (i = 0; i < a.length; i++) a[i] = b[i] = i & 0xff;
|
||||
t.ok(nacl.verify(a, b), 'equal arrays should verify');
|
||||
t.ok(nacl.verify(a, a), 'same arrays should verify');
|
||||
b[0] = 255;
|
||||
t.notOk(nacl.verify(a, b), 'different arrays don\'t verify');
|
||||
t.notOk(nacl.verify(new Uint8Array(1), new Uint8Array(10)), 'arrays of different lengths should not verify');
|
||||
t.notOk(nacl.verify(new Uint8Array(0), new Uint8Array(0)), 'zero-length arrays should not verify');
|
||||
t.end();
|
||||
});
|
||||
@ -1,16 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
test('nacl.randomBytes', function(t) {
|
||||
t.plan(1);
|
||||
var set = {}, s, i;
|
||||
for (i = 0; i < 10000; i++) {
|
||||
s = nacl.util.encodeBase64(nacl.randomBytes(32));
|
||||
if (set[s]) {
|
||||
t.fail("duplicate random sequence! ", s);
|
||||
return;
|
||||
}
|
||||
set[s] = true;
|
||||
}
|
||||
t.pass('no collisions');
|
||||
});
|
||||
@ -1,17 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
var specVectors = require('./data/onetimeauth.spec');
|
||||
|
||||
var enc = nacl.util.encodeBase64,
|
||||
dec = nacl.util.decodeBase64;
|
||||
|
||||
test('nacl.lowlevel.crypto_onetimeauth specified vectors', function(t) {
|
||||
var out = new Uint8Array(16);
|
||||
specVectors.forEach(function(v) {
|
||||
nacl.lowlevel.crypto_onetimeauth(out, 0, v.m, 0, v.m.length, v.k);
|
||||
t.equal(enc(out), enc(v.out));
|
||||
});
|
||||
t.end();
|
||||
});
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
var randomVectors = require('./data/secretbox.random');
|
||||
|
||||
var enc = nacl.util.encodeBase64,
|
||||
dec = nacl.util.decodeBase64;
|
||||
|
||||
test('nacl.secretbox random test vectors', function(t) {
|
||||
randomVectors.forEach(function(vec) {
|
||||
var key = dec(vec[0]);
|
||||
var nonce = dec(vec[1]);
|
||||
var msg = dec(vec[2]);
|
||||
var goodBox = dec(vec[3]);
|
||||
var box = nacl.secretbox(msg, nonce, key);
|
||||
t.ok(box, 'box should be created');
|
||||
t.equal(enc(box), enc(goodBox));
|
||||
var openedBox = nacl.secretbox.open(goodBox, nonce, key);
|
||||
t.ok(openedBox, 'box should open');
|
||||
t.equal(enc(openedBox), enc(msg));
|
||||
});
|
||||
t.end();
|
||||
});
|
||||
|
||||
@ -1,52 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
var enc = nacl.util.encodeBase64,
|
||||
dec = nacl.util.decodeBase64;
|
||||
|
||||
test('nacl.secretbox and nacl.secretbox.open', function(t) {
|
||||
var key = new Uint8Array(nacl.secretbox.keyLength);
|
||||
var nonce = new Uint8Array(nacl.secretbox.nonceLength);
|
||||
for (var i = 0; i < key.length; i++) key[i] = i & 0xff;
|
||||
for (i = 0; i < nonce.length; i++) nonce[i] = (32+i) & 0xff;
|
||||
var msg = nacl.util.decodeUTF8('message to encrypt');
|
||||
var box = nacl.secretbox(msg, nonce, key);
|
||||
var openedMsg = nacl.secretbox.open(box, nonce, key);
|
||||
t.equal(nacl.util.encodeUTF8(openedMsg), nacl.util.encodeUTF8(msg), 'opened messages should be equal');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.secretbox.open with invalid box', function(t) {
|
||||
var key = new Uint8Array(nacl.secretbox.keyLength);
|
||||
var nonce = new Uint8Array(nacl.secretbox.nonceLength);
|
||||
t.equal(nacl.secretbox.open(new Uint8Array(0), nonce, key), false);
|
||||
t.equal(nacl.secretbox.open(new Uint8Array(10), nonce, key), false);
|
||||
t.equal(nacl.secretbox.open(new Uint8Array(100), nonce, key), false);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.secretbox.open with invalid nonce', function(t) {
|
||||
var key = new Uint8Array(nacl.secretbox.keyLength);
|
||||
var nonce = new Uint8Array(nacl.secretbox.nonceLength);
|
||||
for (i = 0; i < nonce.length; i++) nonce[i] = i & 0xff;
|
||||
var msg = nacl.util.decodeUTF8('message to encrypt');
|
||||
var box = nacl.secretbox(msg, nonce, key);
|
||||
t.equal(nacl.util.encodeUTF8(nacl.secretbox.open(box, nonce, key)),
|
||||
nacl.util.encodeUTF8(msg));
|
||||
nonce[0] = 255;
|
||||
t.equal(nacl.secretbox.open(box, nonce, key), false);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.secretbox.open with invalid key', function(t) {
|
||||
var key = new Uint8Array(nacl.secretbox.keyLength);
|
||||
for (var i = 0; i < key.length; i++) key[i] = i & 0xff;
|
||||
var nonce = new Uint8Array(nacl.secretbox.nonceLength);
|
||||
var msg = nacl.util.decodeUTF8('message to encrypt');
|
||||
var box = nacl.secretbox(msg, nonce, key);
|
||||
t.equal(nacl.util.encodeUTF8(nacl.secretbox.open(box, nonce, key)),
|
||||
nacl.util.encodeUTF8(msg));
|
||||
key[0] = 255;
|
||||
t.equal(nacl.secretbox.open(box, nonce, key), false);
|
||||
t.end();
|
||||
});
|
||||
@ -1,43 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
var randomVectors = require('./data/scalarmult.random');
|
||||
|
||||
var enc = nacl.util.encodeBase64,
|
||||
dec = nacl.util.decodeBase64;
|
||||
|
||||
test('nacl.scalarMult.base', function(t) {
|
||||
// This takes takes a bit of time.
|
||||
// Similar to https://code.google.com/p/go/source/browse/curve25519/curve25519_test.go?repo=crypto
|
||||
var golden = new Uint8Array([0x89, 0x16, 0x1f, 0xde, 0x88, 0x7b, 0x2b, 0x53, 0xde, 0x54,
|
||||
0x9a, 0xf4, 0x83, 0x94, 0x01, 0x06, 0xec, 0xc1, 0x14, 0xd6, 0x98, 0x2d,
|
||||
0xaa, 0x98, 0x25, 0x6d, 0xe2, 0x3b, 0xdf, 0x77, 0x66, 0x1a]);
|
||||
var input = new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
||||
for (var i = 0; i < 200; i++) {
|
||||
input = nacl.scalarMult.base(input);
|
||||
}
|
||||
t.equal(enc(input), enc(golden));
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.scalarMult and nacl.scalarMult.base random test vectors', function(t) {
|
||||
randomVectors.forEach(function(vec) {
|
||||
var pk1 = dec(vec[0]);
|
||||
var sk1 = dec(vec[1]);
|
||||
var pk2 = dec(vec[2]);
|
||||
var sk2 = dec(vec[3]);
|
||||
var out = dec(vec[4]);
|
||||
|
||||
var jpk1 = nacl.scalarMult.base(sk1);
|
||||
t.equal(enc(jpk1), enc(pk1));
|
||||
var jpk2 = nacl.scalarMult.base(sk2);
|
||||
t.equal(enc(jpk2), enc(pk2));
|
||||
var jout1 = nacl.scalarMult(sk1, pk2);
|
||||
t.equal(enc(jout1), enc(out));
|
||||
var jout2 = nacl.scalarMult(sk2, pk1);
|
||||
t.equal(enc(jout2), enc(out));
|
||||
});
|
||||
t.end();
|
||||
});
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
var randomVectors = require('./data/box.random');
|
||||
|
||||
var enc = nacl.util.encodeBase64,
|
||||
dec = nacl.util.decodeBase64;
|
||||
|
||||
test('nacl.box random test vectors', function(t) {
|
||||
var nonce = new Uint8Array(nacl.box.nonceLength);
|
||||
randomVectors.forEach(function(vec) {
|
||||
var pk1 = dec(vec[0]);
|
||||
var sk2 = dec(vec[1]);
|
||||
var msg = dec(vec[2]);
|
||||
var goodBox = dec(vec[3]);
|
||||
var box = nacl.box(msg, nonce, pk1, sk2);
|
||||
t.equal(enc(box), enc(goodBox));
|
||||
var openedBox = nacl.box.open(goodBox, nonce, pk1, sk2);
|
||||
t.equal(enc(openedBox), enc(msg));
|
||||
});
|
||||
t.end();
|
||||
});
|
||||
@ -1,78 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
var enc = nacl.util.encodeBase64,
|
||||
dec = nacl.util.decodeBase64;
|
||||
|
||||
test('nacl.box.keyPair', function(t) {
|
||||
var keys = nacl.box.keyPair();
|
||||
t.ok(keys.secretKey && keys.secretKey.length === nacl.box.secretKeyLength, 'has secret key');
|
||||
t.ok(keys.publicKey && keys.publicKey.length === nacl.box.publicKeyLength, 'has public key');
|
||||
t.notEqual(enc(keys.secretKey), enc(keys.publicKey));
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.box.keyPair.fromSecretKey', function(t) {
|
||||
var k1 = nacl.box.keyPair();
|
||||
var k2 = nacl.box.keyPair.fromSecretKey(k1.secretKey);
|
||||
t.equal(enc(k2.secretKey), enc(k1.secretKey));
|
||||
t.equal(enc(k2.publicKey), enc(k1.publicKey));
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.box and nacl.box.open', function(t) {
|
||||
var clientKeys = nacl.box.keyPair();
|
||||
var serverKeys = nacl.box.keyPair();
|
||||
var nonce = new Uint8Array(nacl.box.nonceLength);
|
||||
for (i = 0; i < nonce.length; i++) nonce[i] = (32+i) & 0xff;
|
||||
var msg = nacl.util.decodeUTF8('message to encrypt');
|
||||
var clientBox = nacl.box(msg, nonce, serverKeys.publicKey, clientKeys.secretKey);
|
||||
var clientMsg = nacl.box.open(clientBox, nonce, clientKeys.publicKey, serverKeys.secretKey);
|
||||
t.equal(nacl.util.encodeUTF8(clientMsg), nacl.util.encodeUTF8(msg));
|
||||
var serverBox = nacl.box(msg, nonce, clientKeys.publicKey, serverKeys.secretKey);
|
||||
t.equal(enc(clientBox), enc(serverBox));
|
||||
var serverMsg = nacl.box.open(serverBox, nonce, serverKeys.publicKey, clientKeys.secretKey);
|
||||
t.equal(nacl.util.encodeUTF8(serverMsg), nacl.util.encodeUTF8(msg));
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.box.open with invalid box', function(t) {
|
||||
var clientKeys = nacl.box.keyPair();
|
||||
var serverKeys = nacl.box.keyPair();
|
||||
var nonce = new Uint8Array(nacl.box.nonceLength);
|
||||
t.equal(nacl.box.open(new Uint8Array(0), nonce, serverKeys.publicKey, clientKeys.secretKey), false);
|
||||
t.equal(nacl.box.open(new Uint8Array(10), nonce, serverKeys.publicKey, clientKeys.secretKey), false);
|
||||
t.equal(nacl.box.open(new Uint8Array(100), nonce, serverKeys.publicKey, clientKeys.secretKey), false);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.box.open with invalid nonce', function(t) {
|
||||
var clientKeys = nacl.box.keyPair();
|
||||
var serverKeys = nacl.box.keyPair();
|
||||
var nonce = new Uint8Array(nacl.box.nonceLength);
|
||||
for (i = 0; i < nonce.length; i++) nonce[i] = i & 0xff;
|
||||
var msg = nacl.util.decodeUTF8('message to encrypt');
|
||||
var box = nacl.box(msg, nonce, clientKeys.publicKey, serverKeys.secretKey);
|
||||
t.equal(nacl.util.encodeUTF8(nacl.box.open(box, nonce, serverKeys.publicKey, clientKeys.secretKey)),
|
||||
nacl.util.encodeUTF8(msg));
|
||||
nonce[0] = 255;
|
||||
t.equal(nacl.box.open(box, nonce, serverKeys.publicKey, clientKeys.secretKey), false);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.box.open with invalid keys', function(t) {
|
||||
var clientKeys = nacl.box.keyPair();
|
||||
var serverKeys = nacl.box.keyPair();
|
||||
var nonce = new Uint8Array(nacl.box.nonceLength);
|
||||
var msg = nacl.util.decodeUTF8('message to encrypt');
|
||||
var box = nacl.box(msg, nonce, clientKeys.publicKey, serverKeys.secretKey);
|
||||
t.equal(nacl.util.encodeUTF8(nacl.box.open(box, nonce, serverKeys.publicKey, clientKeys.secretKey)),
|
||||
nacl.util.encodeUTF8(msg));
|
||||
t.equal(nacl.util.encodeUTF8(nacl.box.open(box, nonce, clientKeys.publicKey, serverKeys.secretKey)),
|
||||
nacl.util.encodeUTF8(msg));
|
||||
badPublicKey = new Uint8Array(nacl.box.publicKeyLength);
|
||||
t.equal(nacl.box.open(box, nonce, badPublicKey, clientKeys.secretKey), false);
|
||||
badSecretKey = new Uint8Array(nacl.box.secretKeyLength);
|
||||
t.equal(nacl.box.open(box, nonce, serverKeys.publicKey, badSecretKey), false);
|
||||
t.end();
|
||||
});
|
||||
@ -1,17 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
var randomVectors = require('./data/hash.random');
|
||||
|
||||
var enc = nacl.util.encodeBase64,
|
||||
dec = nacl.util.decodeBase64;
|
||||
|
||||
test('nacl.hash random test vectors', function(t) {
|
||||
randomVectors.forEach(function(vec) {
|
||||
var msg = dec(vec[0]);
|
||||
var goodHash = dec(vec[1]);
|
||||
var hash = nacl.hash(msg);
|
||||
t.equal(enc(hash), enc(goodHash));
|
||||
});
|
||||
t.end();
|
||||
});
|
||||
@ -1,29 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
var specVectors = require('./data/hash.spec');
|
||||
|
||||
var enc = nacl.util.encodeBase64,
|
||||
dec = nacl.util.decodeBase64;
|
||||
|
||||
test('nacl.hash length', function(t) {
|
||||
t.equal(nacl.hash(new Uint8Array(0)).length, 64);
|
||||
t.equal(nacl.hash(new Uint8Array(100)).length, 64);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.hash exceptions for bad types', function(t) {
|
||||
t.throws(function() { nacl.hash('string'); }, TypeError, 'should throw TypeError for string type');
|
||||
t.throws(function() { nacl.hash([1,2,3]); }, TypeError, 'should throw TypeError for array type');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.hash specified test vectors', function(t) {
|
||||
specVectors.forEach(function(vec) {
|
||||
var goodHash = new Uint8Array(vec[0]);
|
||||
var msg = new Uint8Array(vec[1]);
|
||||
var hash = nacl.hash(msg);
|
||||
t.equal(enc(hash), enc(goodHash));
|
||||
});
|
||||
t.end();
|
||||
});
|
||||
@ -1,38 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
var specVectors = require('./data/sign.spec');
|
||||
|
||||
var enc = nacl.util.encodeBase64,
|
||||
dec = nacl.util.decodeBase64;
|
||||
|
||||
test('nacl.sign and nacl.sign.open specified vectors', function(t) {
|
||||
specVectors.forEach(function(vec) {
|
||||
var keys = nacl.sign.keyPair.fromSecretKey(dec(vec[0]));
|
||||
var msg = dec(vec[1]);
|
||||
var goodSig = dec(vec[2]);
|
||||
|
||||
var signedMsg = nacl.sign(msg, keys.secretKey);
|
||||
t.equal(enc(signedMsg.subarray(0, nacl.sign.signatureLength)), enc(goodSig), 'signatures must be equal');
|
||||
var openedMsg = nacl.sign.open(signedMsg, keys.publicKey);
|
||||
t.equal(enc(openedMsg), enc(msg), 'messages must be equal');
|
||||
});
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.sign.detached and nacl.sign.detached.verify some specified vectors', function(t) {
|
||||
specVectors.forEach(function(vec, i) {
|
||||
// We don't need to test all, as internals are already tested above.
|
||||
if (i % 100 !== 0) return;
|
||||
|
||||
var keys = nacl.sign.keyPair.fromSecretKey(dec(vec[0]));
|
||||
var msg = dec(vec[1]);
|
||||
var goodSig = dec(vec[2]);
|
||||
|
||||
var sig = nacl.sign.detached(msg, keys.secretKey);
|
||||
t.equal(enc(sig), enc(goodSig), 'signatures must be equal');
|
||||
var result = nacl.sign.detached.verify(msg, sig, keys.publicKey);
|
||||
t.ok(result, 'signature must be verified');
|
||||
});
|
||||
t.end();
|
||||
});
|
||||
@ -1,80 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var test = require('tape');
|
||||
|
||||
var enc = nacl.util.encodeBase64,
|
||||
dec = nacl.util.decodeBase64;
|
||||
|
||||
test('nacl.sign.keyPair', function(t) {
|
||||
var keys = nacl.sign.keyPair();
|
||||
t.ok(keys.secretKey && keys.secretKey.length === nacl.sign.secretKeyLength, 'has secret key');
|
||||
t.ok(keys.publicKey && keys.publicKey.length === nacl.sign.publicKeyLength, 'has public key');
|
||||
t.notEqual(enc(keys.secretKey), enc(keys.publicKey));
|
||||
var newKeys = nacl.sign.keyPair();
|
||||
t.notEqual(enc(newKeys.secretKey), enc(keys.secretKey), 'two keys differ');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.sign.keyPair.fromSecretKey', function(t) {
|
||||
var k1 = nacl.sign.keyPair();
|
||||
var k2 = nacl.sign.keyPair.fromSecretKey(k1.secretKey);
|
||||
t.equal(enc(k2.secretKey), enc(k1.secretKey));
|
||||
t.equal(enc(k2.publicKey), enc(k1.publicKey));
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.sign.keyPair.fromSeed', function(t) {
|
||||
var seed = nacl.randomBytes(nacl.sign.seedLength);
|
||||
var k1 = nacl.sign.keyPair.fromSeed(seed);
|
||||
var k2 = nacl.sign.keyPair.fromSeed(seed);
|
||||
t.equal(k1.secretKey.length, nacl.sign.secretKeyLength);
|
||||
t.equal(k1.publicKey.length, nacl.sign.publicKeyLength);
|
||||
t.equal(k2.secretKey.length, nacl.sign.secretKeyLength);
|
||||
t.equal(k2.publicKey.length, nacl.sign.publicKeyLength);
|
||||
t.equal(enc(k2.secretKey), enc(k1.secretKey));
|
||||
t.equal(enc(k2.publicKey), enc(k1.publicKey));
|
||||
var seed2 = nacl.randomBytes(nacl.sign.seedLength);
|
||||
var k3 = nacl.sign.keyPair.fromSeed(seed2);
|
||||
t.equal(k3.secretKey.length, nacl.sign.secretKeyLength);
|
||||
t.equal(k3.publicKey.length, nacl.sign.publicKeyLength);
|
||||
t.notEqual(enc(k3.secretKey), enc(k1.secretKey));
|
||||
t.notEqual(enc(k3.publicKey), enc(k1.publicKey));
|
||||
t.throws(function() { nacl.sign.keyPair.fromSeed(seed2.subarray(0, 16)) }, Error, 'should throw error for wrong seed size');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.sign and nacl.sign.open', function(t) {
|
||||
var k = nacl.sign.keyPair();
|
||||
var m = new Uint8Array(100);
|
||||
for (var i = 0; i < m.length; i++) m[i] = i & 0xff;
|
||||
var sm = nacl.sign(m, k.secretKey);
|
||||
t.ok(sm.length > m.length, 'signed message length should be greater than message length');
|
||||
var om = nacl.sign.open(sm, k.publicKey);
|
||||
t.deepEqual(om, m);
|
||||
t.throws(function() { nacl.sign.open(sm, k.publicKey.subarray(1)) }, Error, 'throws error for wrong public key size');
|
||||
var badPublicKey = new Uint8Array(k.publicKey.length);
|
||||
om = nacl.sign.open(sm, badPublicKey);
|
||||
t.equal(om, null, 'opened message must be null when using wrong public key');
|
||||
for (i = 80; i < 90; i++) sm[i] = 0;
|
||||
om = nacl.sign.open(sm, k.publicKey);
|
||||
t.equal(om, null, 'opened message must be null when opening bad signed message');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nacl.sign.detached and nacl.sign.detached.verify', function(t) {
|
||||
var k = nacl.sign.keyPair();
|
||||
var m = new Uint8Array(100);
|
||||
for (var i = 0; i < m.length; i++) m[i] = i & 0xff;
|
||||
var sig = nacl.sign.detached(m, k.secretKey);
|
||||
t.ok(sig.length === nacl.sign.signatureLength, 'signature must have correct length');
|
||||
var result = nacl.sign.detached.verify(m, sig, k.publicKey);
|
||||
t.ok(result, 'signature must be verified');
|
||||
t.throws(function() { nacl.sign.detached.verify(m, sig, k.publicKey.subarray(1)) }, Error, 'throws error for wrong public key size');
|
||||
t.throws(function() { nacl.sign.detached.verify(m, sig.subarray(1), k.publicKey) }, Error, 'throws error for wrong signature size');
|
||||
var badPublicKey = new Uint8Array(k.publicKey.length);
|
||||
result = nacl.sign.detached.verify(m, sig, badPublicKey);
|
||||
t.equal(result, false, 'signature must not be verified with wrong public key');
|
||||
for (i = 0; i < 10; i++) sig[i] = 0;
|
||||
result = nacl.sign.detached.verify(m, sig, k.publicKey);
|
||||
t.equal(result, false, 'bad signature must not be verified');
|
||||
t.end();
|
||||
});
|
||||
@ -1,11 +0,0 @@
|
||||
This directory contains benchmarks that run in Node.js and browsers.
|
||||
|
||||
To run benchmarks in Node.js, from the root project directory:
|
||||
|
||||
$ npm run bench
|
||||
|
||||
alternatively, in this directory, run:
|
||||
|
||||
$ node bench.js
|
||||
|
||||
To run benchmarks in a browser, open bench.html.
|
||||
@ -1,13 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>TweetNaCl-js Benchmarks (fast)</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>TweetNaCl-js Benchmarks (fast)</h1>
|
||||
<script src="../../nacl-fast.min.js"></script>
|
||||
<script src="helpers.js"></script>
|
||||
<script src="bench.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,13 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>TweetNaCl-js Benchmarks</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>TweetNaCl-js Benchmarks</h1>
|
||||
<script src="../../nacl.min.js"></script>
|
||||
<script src="helpers.js"></script>
|
||||
<script src="bench.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,164 +0,0 @@
|
||||
var nacl = (typeof window !== 'undefined') ? window.nacl : require('../../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var helpers = (typeof require !== 'undefined') ? require('./helpers') : window.helpers;
|
||||
var log = helpers.log;
|
||||
|
||||
if (!nacl) throw new Error('nacl not loaded');
|
||||
|
||||
function benchmark(fn, bytes, num) {
|
||||
if (!num) num = 1000;
|
||||
var i, elapsed, start = new Date();
|
||||
while (1) {
|
||||
for (i = 0; i < num; i++) fn();
|
||||
elapsed = (new Date()) - start;
|
||||
if (elapsed < 500) {
|
||||
num += num*1000/elapsed/2;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
log.print(' ' + ((bytes*num/1024/1024*1000)/elapsed).toFixed(3), 'MB/s');
|
||||
log.print(' ' + ((num*1000)/elapsed).toFixed(3), 'ops/s');
|
||||
}
|
||||
|
||||
function benchmarkOps(fn, num) {
|
||||
var i, elapsed, start = new Date();
|
||||
while (1) {
|
||||
for (i = 0; i < num; i++) {
|
||||
fn();
|
||||
}
|
||||
elapsed = (new Date()) - start;
|
||||
if (elapsed < 500) {
|
||||
num += num*1000/elapsed/2;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
log.print(' ' + ((num*1000)/elapsed).toFixed(3), 'ops/s');
|
||||
}
|
||||
|
||||
function crypto_stream_xor_benchmark() {
|
||||
log.start('Benchmarking crypto_stream_xor');
|
||||
var m = new Uint8Array(1024),
|
||||
n = new Uint8Array(24),
|
||||
k = new Uint8Array(32),
|
||||
out = new Uint8Array(1024);
|
||||
for (i = 0; i < 1024; i++) m[i] = i & 255;
|
||||
for (i = 0; i < 24; i++) n[i] = i;
|
||||
for (i = 0; i < 32; i++) k[i] = i;
|
||||
benchmark(function(){
|
||||
nacl.lowlevel.crypto_stream_xor(out, 0, m, 0, m.length, n, k);
|
||||
}, m.length);
|
||||
}
|
||||
|
||||
function crypto_onetimeauth_benchmark() {
|
||||
log.start('Benchmarking crypto_onetimeauth');
|
||||
var m = new Uint8Array(1024),
|
||||
out = new Uint8Array(1024),
|
||||
k = new Uint8Array([0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1]);
|
||||
for (i = 0; i < 1024; i++) {
|
||||
m[i] = i & 255;
|
||||
}
|
||||
benchmark(function(){
|
||||
nacl.lowlevel.crypto_onetimeauth(out, 0, m, 0, m.length, k);
|
||||
}, m.length);
|
||||
}
|
||||
|
||||
function crypto_secretbox_benchmark() {
|
||||
log.start('Benchmarking crypto_secretbox');
|
||||
var i, k = new Uint8Array(32), n = new Uint8Array(24),
|
||||
m = new Uint8Array(1024), c = new Uint8Array(1024);
|
||||
for (i = 0; i < 32; i++) k[i] = 1;
|
||||
for (i = 0; i < 24; i++) n[i] = 2;
|
||||
for (i = 0; i < 1024; i++) m[i] = 3;
|
||||
benchmark(function() {
|
||||
nacl.lowlevel.crypto_secretbox(c, m, m.length, n, k);
|
||||
}, m.length);
|
||||
}
|
||||
|
||||
function secretbox_seal_open_benchmark() {
|
||||
var key = new Uint8Array(32),
|
||||
nonce = new Uint8Array(24),
|
||||
msg = new Uint8Array(1024),
|
||||
box, i;
|
||||
for (i = 0; i < 32; i++) key[i] = 1;
|
||||
for (i = 0; i < 24; i++) nonce[i] = 2;
|
||||
for (i = 0; i < 1024; i++) msg[i] = 3;
|
||||
|
||||
log.start('Benchmarking secretbox');
|
||||
benchmark(function() {
|
||||
box = nacl.secretbox(msg, nonce, key);
|
||||
}, msg.length);
|
||||
log.start('Benchmarking secretbox.open');
|
||||
benchmark(function() {
|
||||
nacl.secretbox.open(box, nonce, key);
|
||||
}, msg.length);
|
||||
}
|
||||
|
||||
function crypto_scalarmult_base_benchmark() {
|
||||
log.start('Benchmarking crypto_scalarmult_base');
|
||||
var n = new Uint8Array(32), q = new Uint8Array(32);
|
||||
for (var i = 0; i < 32; i++) n[i] = i;
|
||||
benchmarkOps(function() {
|
||||
nacl.lowlevel.crypto_scalarmult_base(q, n);
|
||||
}, 10);
|
||||
}
|
||||
|
||||
function box_seal_open_benchmark() {
|
||||
var pk1 = new Uint8Array(32), sk1 = new Uint8Array(32),
|
||||
pk2 = new Uint8Array(32), sk2 = new Uint8Array(32);
|
||||
nacl.lowlevel.crypto_box_keypair(pk1, sk1);
|
||||
nacl.lowlevel.crypto_box_keypair(pk2, sk2);
|
||||
var nonce = nacl.util.decodeUTF8('123456789012345678901234');
|
||||
var msg = nacl.util.decodeUTF8((new Array(1024)).join('a'));
|
||||
var box = null;
|
||||
log.start('Benchmarking box');
|
||||
benchmark(function() {
|
||||
box = nacl.box(msg, nonce, pk1, sk2);
|
||||
}, msg.length, 20);
|
||||
log.start('Benchmarking box.open');
|
||||
benchmark(function() {
|
||||
nacl.box.open(box, nonce, pk2, sk1);
|
||||
}, msg.length, 20);
|
||||
}
|
||||
|
||||
function sign_open_benchmark() {
|
||||
var k = nacl.sign.keyPair();
|
||||
var sk = k.secretKey;
|
||||
var pk = k.publicKey;
|
||||
var msg = nacl.util.decodeUTF8((new Array(128)).join('a'));
|
||||
var sm;
|
||||
log.start('Benchmarking sign');
|
||||
benchmark(function() {
|
||||
sm = nacl.sign(msg, sk);
|
||||
}, msg.length, 20);
|
||||
log.start('Benchmarking sign.open');
|
||||
benchmark(function() {
|
||||
nacl.sign.open(sm, pk);
|
||||
}, msg.length, 20);
|
||||
}
|
||||
|
||||
function crypto_hash_benchmark() {
|
||||
log.start('Benchmarking crypto_hash (1024 bytes)');
|
||||
var m = new Uint8Array(1024), out = new Uint8Array(64);
|
||||
for (i = 0; i < m.length; i++) m[i] = i & 255;
|
||||
benchmark(function(){
|
||||
nacl.lowlevel.crypto_hash(out, m, m.length);
|
||||
}, m.length);
|
||||
|
||||
log.start('Benchmarking crypto_hash (16 KiB)');
|
||||
m = new Uint8Array(16*1024);
|
||||
for (i = 0; i < m.length; i++) m[i] = i & 255;
|
||||
benchmark(function(){
|
||||
nacl.lowlevel.crypto_hash(out, m, m.length);
|
||||
}, m.length);
|
||||
}
|
||||
|
||||
crypto_stream_xor_benchmark();
|
||||
crypto_onetimeauth_benchmark();
|
||||
crypto_secretbox_benchmark();
|
||||
crypto_hash_benchmark();
|
||||
secretbox_seal_open_benchmark();
|
||||
crypto_scalarmult_base_benchmark();
|
||||
box_seal_open_benchmark();
|
||||
sign_open_benchmark();
|
||||
@ -1,62 +0,0 @@
|
||||
// Test helpers.
|
||||
(function(exports) {
|
||||
|
||||
function NodeLogger() {
|
||||
this.print = function() {
|
||||
console.log.apply(console, arguments);
|
||||
};
|
||||
|
||||
this.ok = function() {
|
||||
process.stdout.write('.');
|
||||
};
|
||||
|
||||
this.error = function() {
|
||||
console.error.apply(console, arguments);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
this.start = this.print.bind(this, '\n');
|
||||
}
|
||||
|
||||
function BrowserLogger() {
|
||||
var el = document.createElement('pre');
|
||||
document.body.appendChild(el);
|
||||
|
||||
function escape(s) {
|
||||
var reps = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
'/': '/'
|
||||
};
|
||||
return String(s).replace(/[&<>"'\/]/g, function (x) { return reps[x]; });
|
||||
}
|
||||
|
||||
this.print = function() {
|
||||
console.log.apply(console, arguments);
|
||||
var s = escape(arguments.length ? Array.prototype.slice.call(arguments).join(' ') : '');
|
||||
el.innerHTML += s + '\n';
|
||||
};
|
||||
|
||||
this.ok = function() {
|
||||
// No console output.
|
||||
el.innerHTML += '.';
|
||||
};
|
||||
|
||||
this.error = function() {
|
||||
console.error.apply(console, arguments);
|
||||
var s = escape(arguments.length ? Array.prototype.slice.call(arguments) : '');
|
||||
el.innerHTML += 'ERROR: ' + s + '\n';
|
||||
};
|
||||
|
||||
this.start = this.print.bind(this, '\n');
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined')
|
||||
exports.log = new BrowserLogger();
|
||||
else
|
||||
exports.log = new NodeLogger();
|
||||
|
||||
})(typeof exports !== 'undefined' ? exports : (window.helpers = window.helpers || {}));
|
||||
2
src/tweetnacl/test/browser/.gitignore
vendored
2
src/tweetnacl/test/browser/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
_bundle.js
|
||||
_bundle-quick.js
|
||||
@ -1,9 +0,0 @@
|
||||
This directory contains test files for browsers.
|
||||
|
||||
In the root project directory:
|
||||
|
||||
$ npm run browser
|
||||
|
||||
to build new _bundle.js.
|
||||
|
||||
Then open test.html.
|
||||
@ -1,11 +0,0 @@
|
||||
<!doctype html>
|
||||
<title>TweetNaCl.js Tests</title>
|
||||
<body>
|
||||
<h1>Select test to run:</h1>
|
||||
<ul>
|
||||
<li><a href="test.html"><b>Full</b> nacl.min.js</a></li>
|
||||
<li><a href="test-fast.html"><b>Full</b> nacl-fast.min.js</a></li>
|
||||
<li>--</li>
|
||||
<li><a href="test-quick.html"><b>Quick</b> nacl.min.js</a></li>
|
||||
<li><a href="test-quick-fast.html"><b>Quick</b> nacl-fast.min.js</a></li>
|
||||
</body>
|
||||
@ -1 +0,0 @@
|
||||
var _ = require('tap-browser-color')();
|
||||
@ -1,12 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>TweetNaCl-js Tests (fast)</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>TweetNaCl-js Tests (fast)</h1>
|
||||
<script src="../../nacl-fast.min.js"></script>
|
||||
<script src="_bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,12 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>TweetNaCl-js Tests (fast)</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>TweetNaCl-js Tests (fast)</h1>
|
||||
<script src="../../nacl-fast.min.js"></script>
|
||||
<script src="_bundle-quick.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,12 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>TweetNaCl-js Tests</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>TweetNaCl-js Tests</h1>
|
||||
<script src="../../nacl.min.js"></script>
|
||||
<script src="_bundle-quick.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,12 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>TweetNaCl-js Tests</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>TweetNaCl-js Tests</h1>
|
||||
<script src="../../nacl.min.js"></script>
|
||||
<script src="_bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1 +0,0 @@
|
||||
window.nacl = require('../../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
6
src/tweetnacl/test/c/.gitignore
vendored
6
src/tweetnacl/test/c/.gitignore
vendored
@ -1,6 +0,0 @@
|
||||
cscalarmult
|
||||
cbox
|
||||
csecretbox
|
||||
csign
|
||||
chash
|
||||
*.o
|
||||
@ -1,54 +0,0 @@
|
||||
var nacl = require('../../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var crypto = require('crypto');
|
||||
var spawn = require('child_process').spawn;
|
||||
var path = require('path');
|
||||
var test = require('tape');
|
||||
|
||||
function csecretbox(msg, n, k, callback) {
|
||||
var hexk = (new Buffer(k)).toString('hex');
|
||||
var hexn = (new Buffer(n)).toString('hex');
|
||||
var p = spawn(path.resolve(__dirname, 'csecretbox'), [hexk, hexn]);
|
||||
var result = [];
|
||||
p.stdout.on('data', function(data) {
|
||||
result.push(data);
|
||||
});
|
||||
p.on('close', function(code) {
|
||||
return callback(Buffer.concat(result).toString('base64'));
|
||||
});
|
||||
p.on('error', function(err) {
|
||||
throw err;
|
||||
});
|
||||
p.stdin.write(msg);
|
||||
p.stdin.end();
|
||||
}
|
||||
|
||||
test('nacl.secretbox (C)', function(t) {
|
||||
var k = new Uint8Array(nacl.secretbox.keyLength),
|
||||
n = new Uint8Array(nacl.secretbox.nonceLength),
|
||||
i;
|
||||
for (i = 0; i < 32; i++) k[i] = i;
|
||||
for (i = 0; i < 24; i++) n[i] = i;
|
||||
|
||||
function check(num, maxNum, next) {
|
||||
var msg = nacl.randomBytes(num);
|
||||
var box = nacl.util.encodeBase64(nacl.secretbox(msg, n, k));
|
||||
csecretbox(new Buffer(msg), n, k, function(boxFromC) {
|
||||
t.equal(box, boxFromC, 'secretboxes should be equal');
|
||||
t.notEqual(nacl.secretbox.open(nacl.util.decodeBase64(boxFromC), n, k), false, 'opening should succeed');
|
||||
if (num >= maxNum) {
|
||||
if (next) next();
|
||||
return;
|
||||
}
|
||||
check(num+1, maxNum, next);
|
||||
});
|
||||
}
|
||||
|
||||
check(0, 1024, function() {
|
||||
check(16418, 16500, function() {
|
||||
check(1000000, 0, function() {
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@ -1,44 +0,0 @@
|
||||
var NUMBER_OF_TESTS = 1000;
|
||||
|
||||
var nacl = require('../../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var execFile = require('child_process').execFile;
|
||||
var path = require('path');
|
||||
var test = require('tape');
|
||||
|
||||
function cscalarmult(n, p, callback) {
|
||||
var hexN = (new Buffer(n)).toString('hex');
|
||||
var hexP = (new Buffer(p)).toString('hex');
|
||||
|
||||
execFile(path.resolve(__dirname, 'cscalarmult'), [hexN, hexP], function(err, stdout) {
|
||||
if (err) throw err;
|
||||
callback(stdout.toString('utf8'));
|
||||
});
|
||||
}
|
||||
|
||||
test('nacl.scalarMult (C)', function(t) {
|
||||
var k1 = {
|
||||
publicKey: nacl.util.decodeBase64('JRAWWRKVfZS2U/QiV+X2+PaabPfAB4H9p+BZkBN8ji8='),
|
||||
secretKey: nacl.util.decodeBase64('5g1pBmI3HL5GAjtt3/2FZDQVfGSMNohngN7OVSizBVE=')
|
||||
};
|
||||
|
||||
function check(num) {
|
||||
var k2 = nacl.box.keyPair();
|
||||
var q1 = nacl.scalarMult(k1.secretKey, k2.publicKey);
|
||||
var q2 = nacl.scalarMult(k2.secretKey, k1.publicKey);
|
||||
|
||||
t.equal(nacl.util.encodeBase64(q1), nacl.util.encodeBase64(q2),
|
||||
'scalarMult results should be equal');
|
||||
|
||||
hexQ = (new Buffer(q1)).toString('hex');
|
||||
cscalarmult(k1.secretKey, k2.publicKey, function(cQ) {
|
||||
t.equal(hexQ, cQ);
|
||||
if (num >= NUMBER_OF_TESTS) {
|
||||
t.end();
|
||||
return;
|
||||
}
|
||||
check(num+1);
|
||||
});
|
||||
}
|
||||
|
||||
check(0);
|
||||
});
|
||||
@ -1,51 +0,0 @@
|
||||
var nacl = require('../../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var crypto = require('crypto');
|
||||
var spawn = require('child_process').spawn;
|
||||
var path = require('path');
|
||||
var test = require('tape');
|
||||
|
||||
function cbox(msg, sk, pk, n, callback) {
|
||||
var hexsk = (new Buffer(sk)).toString('hex');
|
||||
var hexpk = (new Buffer(pk)).toString('hex');
|
||||
var hexn = (new Buffer(n)).toString('hex');
|
||||
var p = spawn(path.resolve(__dirname, 'cbox'), [hexsk, hexpk, hexn]);
|
||||
var result = [];
|
||||
p.stdout.on('data', function(data) {
|
||||
result.push(data);
|
||||
});
|
||||
p.on('close', function(code) {
|
||||
return callback(Buffer.concat(result).toString('base64'));
|
||||
});
|
||||
p.on('error', function(err) {
|
||||
throw err;
|
||||
});
|
||||
p.stdin.write(msg);
|
||||
p.stdin.end();
|
||||
}
|
||||
|
||||
test('nacl.box (C)', function(t) {
|
||||
var k1 = nacl.box.keyPair();
|
||||
|
||||
function check(num, maxNum, next) {
|
||||
var sk2 = nacl.randomBytes(nacl.box.secretKeyLength);
|
||||
var msg = nacl.randomBytes(num);
|
||||
var nonce = nacl.randomBytes(24);
|
||||
var box = nacl.util.encodeBase64(nacl.box(msg, nonce, k1.publicKey, sk2));
|
||||
cbox(new Buffer(msg), sk2, k1.publicKey, nonce, function(boxFromC) {
|
||||
t.equal(box, boxFromC, 'boxes should be equal');
|
||||
t.notEqual(nacl.box.open(nacl.util.decodeBase64(boxFromC), nonce, k1.publicKey, sk2),
|
||||
false, 'opening box should succeed');
|
||||
if (num >= maxNum) {
|
||||
if (next) next();
|
||||
return;
|
||||
}
|
||||
check(num+1, maxNum, next);
|
||||
});
|
||||
}
|
||||
|
||||
check(0, 1024, function() {
|
||||
check(16417, 16500, function() {
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,39 +0,0 @@
|
||||
var nacl = require('../../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var crypto = require('crypto');
|
||||
var spawn = require('child_process').spawn;
|
||||
var path = require('path');
|
||||
var test = require('tape');
|
||||
|
||||
function chash(msg, callback) {
|
||||
var p = spawn(path.resolve(__dirname, 'chash'));
|
||||
var result = [];
|
||||
p.stdout.on('data', function(data) {
|
||||
result.push(data);
|
||||
});
|
||||
p.on('close', function(code) {
|
||||
return callback(Buffer.concat(result).toString('utf8'));
|
||||
});
|
||||
p.on('error', function(err) {
|
||||
throw err;
|
||||
});
|
||||
p.stdin.write(msg);
|
||||
p.stdin.end();
|
||||
}
|
||||
|
||||
test('nacl.hash (C)', function(t) {
|
||||
function check(num) {
|
||||
var msg = nacl.randomBytes(num);
|
||||
var h = nacl.hash(msg);
|
||||
var hexH = (new Buffer(h)).toString('hex');
|
||||
chash(new Buffer(msg), function(hexCH) {
|
||||
t.equal(hexH, hexCH, 'hashes should be equal');
|
||||
if (num >= 1000) {
|
||||
t.end();
|
||||
return;
|
||||
}
|
||||
check(num+1);
|
||||
});
|
||||
}
|
||||
|
||||
check(0);
|
||||
});
|
||||
@ -1,44 +0,0 @@
|
||||
var nacl = require('../../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var crypto = require('crypto');
|
||||
var spawn = require('child_process').spawn;
|
||||
var path = require('path');
|
||||
var test = require('tape');
|
||||
|
||||
function csign(sk, msg, callback) {
|
||||
var hexsk = (new Buffer(sk)).toString('hex');
|
||||
var p = spawn(path.resolve(__dirname, 'csign'), [hexsk]);
|
||||
var result = [];
|
||||
p.stdout.on('data', function(data) {
|
||||
result.push(data);
|
||||
});
|
||||
p.on('close', function(code) {
|
||||
callback(Buffer.concat(result).toString('base64'));
|
||||
});
|
||||
p.on('error', function(err) {
|
||||
throw err;
|
||||
});
|
||||
p.stdin.write(msg);
|
||||
p.stdin.end();
|
||||
}
|
||||
|
||||
test('nacl.sign (C)', function(t) {
|
||||
function check(num) {
|
||||
var keys = nacl.sign.keyPair();
|
||||
var msg = nacl.randomBytes(num);
|
||||
var signedMsg = nacl.util.encodeBase64(nacl.sign(msg, keys.secretKey));
|
||||
csign(keys.secretKey, new Buffer(msg), function(signedFromC) {
|
||||
t.equal(signedMsg, signedFromC, 'signed messages should be equal');
|
||||
var openedMsg = nacl.sign.open(nacl.util.decodeBase64(signedFromC), keys.publicKey);
|
||||
t.notEqual(openedMsg, null, 'open should succeed');
|
||||
t.equal(nacl.util.encodeBase64(openedMsg), nacl.util.encodeBase64(msg),
|
||||
'messages should be equal');
|
||||
if (num >= 100) {
|
||||
t.end();
|
||||
return;
|
||||
}
|
||||
check(num+1);
|
||||
});
|
||||
}
|
||||
|
||||
check(0);
|
||||
});
|
||||
@ -1,52 +0,0 @@
|
||||
var nacl = require('../../' + (process.env.NACL_SRC || 'nacl.min.js'));
|
||||
var crypto = require('crypto');
|
||||
var spawn = require('child_process').spawn;
|
||||
var execFile = require('child_process').execFile;
|
||||
var path = require('path');
|
||||
var test = require('tape');
|
||||
|
||||
function csign(sk, msg, callback) {
|
||||
var hexsk = (new Buffer(sk)).toString('hex');
|
||||
var p = spawn(path.resolve(__dirname, 'csign'), [hexsk]);
|
||||
var result = [];
|
||||
p.stdout.on('data', function(data) {
|
||||
result.push(data);
|
||||
});
|
||||
p.on('close', function(code) {
|
||||
callback(Buffer.concat(result).toString('base64'));
|
||||
});
|
||||
p.on('error', function(err) {
|
||||
throw err;
|
||||
});
|
||||
p.stdin.write(msg);
|
||||
p.stdin.end();
|
||||
}
|
||||
|
||||
function csignkeypair(callback) {
|
||||
execFile(path.resolve(__dirname, 'csign-keypair'), [], function(err, stdout) {
|
||||
if (err) throw err;
|
||||
callback(stdout.toString('utf8'));
|
||||
});
|
||||
}
|
||||
|
||||
test('nacl.sign (C) with keypair from C', function(t) {
|
||||
function check(num) {
|
||||
csignkeypair(function(hexSecretKey) {
|
||||
var secretKey = new Uint8Array(nacl.sign.secretKeyLength);
|
||||
var b = new Buffer(hexSecretKey, 'hex');
|
||||
for (var i = 0; i < b.length; i++) secretKey[i] = b[i];
|
||||
var msg = nacl.randomBytes(num);
|
||||
var signedMsg = nacl.util.encodeBase64(nacl.sign(msg, secretKey));
|
||||
csign(secretKey, new Buffer(msg), function(signedFromC) {
|
||||
t.equal(signedMsg, signedFromC, 'signed messages should be equal');
|
||||
if (num >= 100) {
|
||||
t.end();
|
||||
return;
|
||||
}
|
||||
check(num+1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
check(0);
|
||||
});
|
||||
@ -1,38 +0,0 @@
|
||||
CFLAGS=-O3
|
||||
|
||||
all: csecretbox cscalarmult cbox chash csign csign-keypair
|
||||
|
||||
csecretbox: csecretbox.o tweetnacl.o
|
||||
|
||||
cscalarmult: cscalarmult.o tweetnacl.o
|
||||
|
||||
cbox: cbox.o tweetnacl.o
|
||||
|
||||
chash: chash.o tweetnacl.o
|
||||
|
||||
csign: csign.o tweetnacl.o
|
||||
|
||||
csign-keypair: csign-keypair.o tweetnacl.o
|
||||
|
||||
test: test_secretbox test_scalarmult test_box test_hash test_sign test_signkeypair clean
|
||||
|
||||
test_secretbox: csecretbox
|
||||
node ./00-secretbox.js
|
||||
|
||||
test_scalarmult: cscalarmult
|
||||
node ./01-scalarmult.js
|
||||
|
||||
test_box: cbox
|
||||
node ./02-box.js
|
||||
|
||||
test_hash: chash
|
||||
node ./03-hash.js
|
||||
|
||||
test_sign: csign
|
||||
node ./04-sign.js
|
||||
|
||||
test_signkeypair: csign csign-keypair
|
||||
node ./05-sign-keypair.js
|
||||
|
||||
clean:
|
||||
rm *.o csecretbox cscalarmult cbox chash csign csign-keypair
|
||||
@ -1,8 +0,0 @@
|
||||
Tests that call C programs based on original tweetnacl.c,
|
||||
and compare results with TweetNaCl-js.
|
||||
|
||||
Work only in Node.js.
|
||||
|
||||
To run, in this directory:
|
||||
|
||||
$ make test
|
||||
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Written by @dchest. Public domain.
|
||||
*/
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tweetnacl.h"
|
||||
|
||||
size_t
|
||||
readmsg(unsigned char **out)
|
||||
{
|
||||
unsigned char buf[4096];
|
||||
size_t n, have = 0;
|
||||
unsigned char *msg = calloc(1, crypto_box_ZEROBYTES);
|
||||
if (msg == NULL)
|
||||
err(1, NULL);
|
||||
have = crypto_box_ZEROBYTES;
|
||||
while (!feof(stdin)) {
|
||||
n = fread(buf, 1, sizeof(buf), stdin);
|
||||
if (n == 0)
|
||||
break;
|
||||
if ((msg = realloc(msg, have + n)) == NULL)
|
||||
err(1, NULL);
|
||||
memcpy(&msg[have], buf, n);
|
||||
have += n;
|
||||
}
|
||||
*out = msg;
|
||||
return have;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
dechexchar(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return (c - 0x30);
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
return (c - 0x37);
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
return (c - 0x57);
|
||||
else
|
||||
errx(1, "not a hex char");
|
||||
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
decodehex(const char *h)
|
||||
{
|
||||
unsigned char *r, *p, a, b;
|
||||
size_t i, len;
|
||||
|
||||
len = strlen(h);
|
||||
if ((r = malloc(len / 2)) == NULL)
|
||||
err(1, NULL);
|
||||
p = r;
|
||||
if (len % 2 != 0)
|
||||
errx(1, "bad hex string length");
|
||||
for (i = 0; i < len; i += 2)
|
||||
*p++ = ((dechexchar(h[i]) * 16) & 0xf0) + (dechexchar(h[i+1]) & 0xf);
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
randombytes(unsigned char *x, long long y)
|
||||
{
|
||||
errx(1, "we don't use randombytes");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
unsigned char *sk, *pk, *n, *m, *c;
|
||||
size_t mlen, clen;
|
||||
|
||||
if (argc < 2) {
|
||||
puts("usage: cbox SK PK NONCE");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strlen(argv[1]) != crypto_box_SECRETKEYBYTES * 2)
|
||||
errx(1, "bad SK length");
|
||||
sk = decodehex(argv[1]);
|
||||
|
||||
if (strlen(argv[2]) != crypto_box_PUBLICKEYBYTES * 2)
|
||||
errx(1, "bad PK length");
|
||||
pk = decodehex(argv[2]);
|
||||
|
||||
if (strlen(argv[3]) != crypto_box_NONCEBYTES * 2)
|
||||
errx(1, "bad NONCE length");
|
||||
n = decodehex(argv[3]);
|
||||
|
||||
mlen = readmsg(&m);
|
||||
if ((c = calloc(mlen, 1)) == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
crypto_box(c, m, mlen, n, pk, sk);
|
||||
c += crypto_box_BOXZEROBYTES;
|
||||
clen = mlen - crypto_box_BOXZEROBYTES;
|
||||
|
||||
if (fwrite(c, 1, clen, stdout) != clen)
|
||||
err(1, NULL);
|
||||
return 0;
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* This program sings a message using tweetnacl.c.
|
||||
* Written by @dchest. Public domain.
|
||||
*/
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tweetnacl.h"
|
||||
|
||||
size_t
|
||||
readmsg(unsigned char **out)
|
||||
{
|
||||
unsigned char buf[4096];
|
||||
unsigned char *msg = NULL;
|
||||
size_t n, have = 0;
|
||||
while (!feof(stdin)) {
|
||||
n = fread(buf, 1, sizeof(buf), stdin);
|
||||
if (n == 0)
|
||||
break;
|
||||
if ((msg = realloc(msg, have + n)) == NULL)
|
||||
err(1, NULL);
|
||||
memcpy(&msg[have], buf, n);
|
||||
have += n;
|
||||
}
|
||||
*out = msg;
|
||||
return have;
|
||||
}
|
||||
|
||||
void
|
||||
randombytes(unsigned char *x, long long y)
|
||||
{
|
||||
errx(1, "we don't use randombytes");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
unsigned char *m, h[crypto_hash_BYTES];
|
||||
size_t mlen, i;
|
||||
|
||||
mlen = readmsg(&m);
|
||||
crypto_hash(h, m, mlen);
|
||||
for (i = 0; i < sizeof(h); i++)
|
||||
printf("%02x", h[i]);
|
||||
return 0;
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Written by @dchest. Public domain.
|
||||
*/
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tweetnacl.h"
|
||||
|
||||
unsigned char
|
||||
dechexchar(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return (c - 0x30);
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
return (c - 0x37);
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
return (c - 0x57);
|
||||
else
|
||||
errx(1, "not a hex char");
|
||||
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
decodehex(const char *h)
|
||||
{
|
||||
unsigned char *r, *p, a, b;
|
||||
size_t i, len;
|
||||
|
||||
len = strlen(h);
|
||||
if (len == 0 || len % 2 != 0)
|
||||
errx(1, "bad hex string length");
|
||||
if ((r = malloc(len / 2)) == NULL)
|
||||
err(1, NULL);
|
||||
p = r;
|
||||
for (i = 0; i < len; i += 2)
|
||||
*p++ = ((dechexchar(h[i]) * 16) & 0xf0) + (dechexchar(h[i+1]) & 0xf);
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
randombytes(unsigned char *x, long long y)
|
||||
{
|
||||
errx(1, "we don't use randombytes");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
unsigned char *n, *p, q[crypto_scalarmult_BYTES];
|
||||
size_t i;
|
||||
|
||||
if (argc < 2) {
|
||||
puts("usage: cscalarmult N P");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strlen(argv[1]) != crypto_scalarmult_SCALARBYTES * 2)
|
||||
errx(1, "bad N length");
|
||||
n = decodehex(argv[1]);
|
||||
|
||||
if (strlen(argv[2]) != crypto_scalarmult_SCALARBYTES * 2)
|
||||
errx(1, "bad P length");
|
||||
p = decodehex(argv[2]);
|
||||
|
||||
crypto_scalarmult(q, n, p);
|
||||
|
||||
for (i = 0; i < sizeof(q); i++)
|
||||
printf("%02x", q[i]);
|
||||
return 0;
|
||||
}
|
||||
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Written by @dchest. Public domain.
|
||||
*/
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tweetnacl.h"
|
||||
|
||||
size_t
|
||||
readmsg(unsigned char **out)
|
||||
{
|
||||
unsigned char buf[4096];
|
||||
size_t n, have = 0;
|
||||
unsigned char *msg = calloc(1, crypto_secretbox_ZEROBYTES);
|
||||
if (msg == NULL)
|
||||
err(1, NULL);
|
||||
have = crypto_secretbox_ZEROBYTES;
|
||||
while (!feof(stdin)) {
|
||||
n = fread(buf, 1, sizeof(buf), stdin);
|
||||
if (n == 0)
|
||||
break;
|
||||
if ((msg = realloc(msg, have + n)) == NULL)
|
||||
err(1, NULL);
|
||||
memcpy(&msg[have], buf, n);
|
||||
have += n;
|
||||
}
|
||||
*out = msg;
|
||||
return have;
|
||||
}
|
||||
|
||||
unsigned char
|
||||
dechexchar(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return (c - 0x30);
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
return (c - 0x37);
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
return (c - 0x57);
|
||||
else
|
||||
errx(1, "not a hex char");
|
||||
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
decodehex(const char *h)
|
||||
{
|
||||
unsigned char *r, *p, a, b;
|
||||
size_t i, len;
|
||||
|
||||
len = strlen(h);
|
||||
if ((r = malloc(len / 2)) == NULL)
|
||||
err(1, NULL);
|
||||
p = r;
|
||||
if (len % 2 != 0)
|
||||
errx(1, "bad hex string length");
|
||||
for (i = 0; i < len; i += 2)
|
||||
*p++ = ((dechexchar(h[i]) * 16) & 0xf0) + (dechexchar(h[i+1]) & 0xf);
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
randombytes(unsigned char *x, long long y)
|
||||
{
|
||||
errx(1, "we don't use randombytes");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
unsigned char *k, *n, *m, *c;
|
||||
size_t mlen, clen;
|
||||
|
||||
if (argc < 2) {
|
||||
puts("usage: csecretbox KEY NONCE");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strlen(argv[1]) != crypto_secretbox_KEYBYTES * 2)
|
||||
errx(1, "bad KEY length");
|
||||
k = decodehex(argv[1]);
|
||||
|
||||
if (strlen(argv[2]) != crypto_secretbox_NONCEBYTES * 2)
|
||||
errx(1, "bad NONCE length");
|
||||
n = decodehex(argv[2]);
|
||||
|
||||
mlen = readmsg(&m);
|
||||
|
||||
#if 0
|
||||
FILE *f = fopen("csecretbox_debug.txt", "w");
|
||||
fwrite(m, 1, mlen, f);
|
||||
fclose(f);
|
||||
#endif
|
||||
|
||||
if ((c = calloc(mlen, 1)) == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
crypto_secretbox(c, m, mlen, n, k);
|
||||
c += crypto_secretbox_BOXZEROBYTES;
|
||||
clen = mlen - crypto_secretbox_BOXZEROBYTES;
|
||||
|
||||
if (fwrite(c, 1, clen, stdout) != clen)
|
||||
err(1, NULL);
|
||||
return 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user