Gitlab@Informatics

Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
  • 65160381/project-melon
1 result
Select Git revision
Loading items
Show changes
Showing
with 2490 additions and 0 deletions
File added
{
"name": "bcrypt",
"description": "A bcrypt library for NodeJS.",
"keywords": [
"bcrypt",
"password",
"auth",
"authentication",
"encryption",
"crypt",
"crypto"
],
"main": "./bcrypt",
"version": "5.1.1",
"author": "Nick Campbell (https://github.com/ncb000gt)",
"engines": {
"node": ">= 10.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/kelektiv/node.bcrypt.js.git"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/kelektiv/node.bcrypt.js/issues"
},
"scripts": {
"test": "npm ci --build-from-source && jest",
"install": "node-pre-gyp install --fallback-to-build"
},
"dependencies": {
"@mapbox/node-pre-gyp": "^1.0.11",
"node-addon-api": "^5.0.0"
},
"devDependencies": {
"jest": "^29.6.2"
},
"contributors": [
"Antonio Salazar Cardozo <savedfastcool@gmail.com> (https://github.com/Shadowfiend)",
"Van Nguyen <the.gol.effect@gmail.com> (https://github.com/thegoleffect)",
"David Trejo <david@dtrejo.com> (https://github.com/dtrejo)",
"Ben Glow <glen.low@pixelglow.com> (https://github.com/pixelglow)",
"NewITFarmer.com <> (https://github.com/newitfarmer)",
"Alfred Westerveld <alfredwesterveld@gmail.com> (https://github.com/alfredwesterveld)",
"Vincent Côté-Roy <vincentcr@gmail.com> (https://github.com/vincentcr)",
"Lloyd Hilaiel <lloyd@hilaiel.com> (https://github.com/lloyd)",
"Roman Shtylman <shtylman@gmail.com> (https://github.com/shtylman)",
"Vadim Graboys <dimva13@gmail.com> (https://github.com/vadimg)",
"Ben Noorduis <> (https://github.com/bnoordhuis)",
"Nate Rajlich <nathan@tootallnate.net> (https://github.com/tootallnate)",
"Sean McArthur <sean.monstar@gmail.com> (https://github.com/seanmonstar)",
"Fanie Oosthuysen <fanie.oosthuysen@gmail.com> (https://github.com/weareu)",
"Amitosh Swain Mahapatra <amitosh.swain@gmail.com> (https://github.com/Agathver)",
"Corbin Crutchley <crutchcorn@gmail.com> (https://github.com/crutchcorn)",
"Nicola Del Gobbo <nicoladelgobbo@gmail.com> (https://github.com/NickNaso)"
],
"binary": {
"module_name": "bcrypt_lib",
"module_path": "./lib/binding/napi-v{napi_build_version}",
"package_name": "{module_name}-v{version}-napi-v{napi_build_version}-{platform}-{arch}-{libc}.tar.gz",
"host": "https://github.com",
"remote_path": "kelektiv/node.bcrypt.js/releases/download/v{version}",
"napi_versions": [
3
]
}
}
'use strict';
var Promise = global.Promise;
/// encapsulate a method with a node-style callback in a Promise
/// @param {object} 'this' of the encapsulated function
/// @param {function} function to be encapsulated
/// @param {Array-like} args to be passed to the called function
/// @return {Promise} a Promise encapsulating the function
module.exports.promise = function (fn, context, args) {
if (!Array.isArray(args)) {
args = Array.prototype.slice.call(args);
}
if (typeof fn !== 'function') {
return Promise.reject(new Error('fn must be a function'));
}
return new Promise(function(resolve, reject) {
args.push(function(err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
fn.apply(context, args);
});
};
/// @param {err} the error to be thrown
module.exports.reject = function (err) {
return Promise.reject(err);
};
/// changes the promise implementation that bcrypt uses
/// @param {Promise} the implementation to use
module.exports.use = function(promise) {
Promise = promise;
};
/* $OpenBSD: bcrypt.c,v 1.31 2014/03/22 23:02:03 tedu Exp $ */
/*
* Copyright (c) 1997 Niels Provos <provos@umich.edu>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* This password hashing algorithm was designed by David Mazieres
* <dm@lcs.mit.edu> and works as follows:
*
* 1. state := InitState ()
* 2. state := ExpandKey (state, salt, password)
* 3. REPEAT rounds:
* state := ExpandKey (state, 0, password)
* state := ExpandKey (state, 0, salt)
* 4. ctext := "OrpheanBeholderScryDoubt"
* 5. REPEAT 64:
* ctext := Encrypt_ECB (state, ctext);
* 6. RETURN Concatenate (salt, ctext);
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include "node_blf.h"
#ifdef _WIN32
#define snprintf _snprintf
#endif
//#if !defined(__APPLE__) && !defined(__MACH__)
//#include "bsd/stdlib.h"
//#endif
/* This implementation is adaptable to current computing power.
* You can have up to 2^31 rounds which should be enough for some
* time to come.
*/
static void encode_base64(u_int8_t *, u_int8_t *, u_int16_t);
static void decode_base64(u_int8_t *, u_int16_t, u_int8_t *);
const static char* error = ":";
const static u_int8_t Base64Code[] =
"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const static u_int8_t index_64[128] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 0, 1, 54, 55,
56, 57, 58, 59, 60, 61, 62, 63, 255, 255,
255, 255, 255, 255, 255, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
255, 255, 255, 255, 255, 255, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 255, 255, 255, 255, 255
};
#define CHAR64(c) ( (c) > 127 ? 255 : index_64[(c)])
static void
decode_base64(u_int8_t *buffer, u_int16_t len, u_int8_t *data)
{
u_int8_t *bp = buffer;
u_int8_t *p = data;
u_int8_t c1, c2, c3, c4;
while (bp < buffer + len) {
c1 = CHAR64(*p);
c2 = CHAR64(*(p + 1));
/* Invalid data */
if (c1 == 255 || c2 == 255)
break;
*bp++ = (c1 << 2) | ((c2 & 0x30) >> 4);
if (bp >= buffer + len)
break;
c3 = CHAR64(*(p + 2));
if (c3 == 255)
break;
*bp++ = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
if (bp >= buffer + len)
break;
c4 = CHAR64(*(p + 3));
if (c4 == 255)
break;
*bp++ = ((c3 & 0x03) << 6) | c4;
p += 4;
}
}
void
encode_salt(char *salt, u_int8_t *csalt, char minor, u_int16_t clen, u_int8_t logr)
{
salt[0] = '$';
salt[1] = BCRYPT_VERSION;
salt[2] = minor;
salt[3] = '$';
// Max rounds are 31
snprintf(salt + 4, 4, "%2.2u$", logr & 0x001F);
encode_base64((u_int8_t *) salt + 7, csalt, clen);
}
/* Generates a salt for this version of crypt.
Since versions may change. Keeping this here
seems sensible.
from: http://mail-index.netbsd.org/tech-crypto/2002/05/24/msg000204.html
*/
void
bcrypt_gensalt(char minor, u_int8_t log_rounds, u_int8_t *seed, char *gsalt)
{
if (log_rounds < 4)
log_rounds = 4;
else if (log_rounds > 31)
log_rounds = 31;
encode_salt(gsalt, seed, minor, BCRYPT_MAXSALT, log_rounds);
}
/* We handle $Vers$log2(NumRounds)$salt+passwd$
i.e. $2$04$iwouldntknowwhattosayetKdJ6iFtacBqJdKe6aW7ou */
void
bcrypt(const char *key, size_t key_len, const char *salt, char *encrypted)
{
blf_ctx state;
u_int32_t rounds, i, k;
u_int16_t j;
u_int8_t salt_len, logr, minor;
u_int8_t ciphertext[4 * BCRYPT_BLOCKS+1] = "OrpheanBeholderScryDoubt";
u_int8_t csalt[BCRYPT_MAXSALT];
u_int32_t cdata[BCRYPT_BLOCKS];
int n;
/* Discard "$" identifier */
salt++;
if (*salt > BCRYPT_VERSION) {
/* How do I handle errors ? Return ':' */
strcpy(encrypted, error);
return;
}
/* Check for minor versions */
if (salt[1] != '$') {
switch (salt[1]) {
case 'a': /* 'ab' should not yield the same as 'abab' */
case 'b': /* cap input length at 72 bytes */
minor = salt[1];
salt++;
break;
default:
strcpy(encrypted, error);
return;
}
} else
minor = 0;
/* Discard version + "$" identifier */
salt += 2;
if (salt[2] != '$') {
/* Out of sync with passwd entry */
strcpy(encrypted, error);
return;
}
/* Computer power doesn't increase linear, 2^x should be fine */
n = atoi(salt);
if (n > 31 || n < 0) {
strcpy(encrypted, error);
return;
}
logr = (u_int8_t)n;
if ((rounds = (u_int32_t) 1 << logr) < BCRYPT_MINROUNDS) {
strcpy(encrypted, error);
return;
}
/* Discard num rounds + "$" identifier */
salt += 3;
if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT) {
strcpy(encrypted, error);
return;
}
/* We dont want the base64 salt but the raw data */
decode_base64(csalt, BCRYPT_MAXSALT, (u_int8_t *) salt);
salt_len = BCRYPT_MAXSALT;
if (minor <= 'a')
key_len = (u_int8_t)(key_len + (minor >= 'a' ? 1 : 0));
else
{
/* cap key_len at the actual maximum supported
* length here to avoid integer wraparound */
if (key_len > 72)
key_len = 72;
key_len++; /* include the NUL */
}
/* Setting up S-Boxes and Subkeys */
Blowfish_initstate(&state);
Blowfish_expandstate(&state, csalt, salt_len,
(u_int8_t *) key, key_len);
for (k = 0; k < rounds; k++) {
Blowfish_expand0state(&state, (u_int8_t *) key, key_len);
Blowfish_expand0state(&state, csalt, salt_len);
}
/* This can be precomputed later */
j = 0;
for (i = 0; i < BCRYPT_BLOCKS; i++)
cdata[i] = Blowfish_stream2word(ciphertext, 4 * BCRYPT_BLOCKS, &j);
/* Now do the encryption */
for (k = 0; k < 64; k++)
blf_enc(&state, cdata, BCRYPT_BLOCKS / 2);
for (i = 0; i < BCRYPT_BLOCKS; i++) {
ciphertext[4 * i + 3] = cdata[i] & 0xff;
cdata[i] = cdata[i] >> 8;
ciphertext[4 * i + 2] = cdata[i] & 0xff;
cdata[i] = cdata[i] >> 8;
ciphertext[4 * i + 1] = cdata[i] & 0xff;
cdata[i] = cdata[i] >> 8;
ciphertext[4 * i + 0] = cdata[i] & 0xff;
}
i = 0;
encrypted[i++] = '$';
encrypted[i++] = BCRYPT_VERSION;
if (minor)
encrypted[i++] = minor;
encrypted[i++] = '$';
snprintf(encrypted + i, 4, "%2.2u$", logr & 0x001F);
encode_base64((u_int8_t *) encrypted + i + 3, csalt, BCRYPT_MAXSALT);
encode_base64((u_int8_t *) encrypted + strlen(encrypted), ciphertext,
4 * BCRYPT_BLOCKS - 1);
memset(&state, 0, sizeof(state));
memset(ciphertext, 0, sizeof(ciphertext));
memset(csalt, 0, sizeof(csalt));
memset(cdata, 0, sizeof(cdata));
}
u_int32_t bcrypt_get_rounds(const char * hash)
{
/* skip past the leading "$" */
if (!hash || *(hash++) != '$') return 0;
/* skip past version */
if (0 == (*hash++)) return 0;
if (*hash && *hash != '$') hash++;
if (*hash++ != '$') return 0;
return atoi(hash);
}
static void
encode_base64(u_int8_t *buffer, u_int8_t *data, u_int16_t len)
{
u_int8_t *bp = buffer;
u_int8_t *p = data;
u_int8_t c1, c2;
while (p < data + len) {
c1 = *p++;
*bp++ = Base64Code[(c1 >> 2)];
c1 = (c1 & 0x03) << 4;
if (p >= data + len) {
*bp++ = Base64Code[c1];
break;
}
c2 = *p++;
c1 |= (c2 >> 4) & 0x0f;
*bp++ = Base64Code[c1];
c1 = (c2 & 0x0f) << 2;
if (p >= data + len) {
*bp++ = Base64Code[c1];
break;
}
c2 = *p++;
c1 |= (c2 >> 6) & 0x03;
*bp++ = Base64Code[c1];
*bp++ = Base64Code[c2 & 0x3f];
}
*bp = '\0';
}
#define NAPI_VERSION 3
#include <napi.h>
#include <string>
#include <cstring>
#include <vector>
#include <stdlib.h> // atoi
#include "node_blf.h"
#define NODE_LESS_THAN (!(NODE_VERSION_AT_LEAST(0, 5, 4)))
namespace {
bool ValidateSalt(const char* salt) {
if (!salt || *salt != '$') {
return false;
}
// discard $
salt++;
if (*salt > BCRYPT_VERSION) {
return false;
}
if (salt[1] != '$') {
switch (salt[1]) {
case 'a':
case 'b':
salt++;
break;
default:
return false;
}
}
// discard version + $
salt += 2;
if (salt[2] != '$') {
return false;
}
int n = atoi(salt);
if (n > 31 || n < 0) {
return false;
}
if (((uint8_t)1 << (uint8_t)n) < BCRYPT_MINROUNDS) {
return false;
}
salt += 3;
if (strlen(salt) * 3 / 4 < BCRYPT_MAXSALT) {
return false;
}
return true;
}
inline char ToCharVersion(const std::string& str) {
return str[0];
}
/* SALT GENERATION */
class SaltAsyncWorker : public Napi::AsyncWorker {
public:
SaltAsyncWorker(const Napi::Function& callback, const std::string& seed, ssize_t rounds, char minor_ver)
: Napi::AsyncWorker(callback, "bcrypt:SaltAsyncWorker"), seed(seed), rounds(rounds), minor_ver(minor_ver) {
}
~SaltAsyncWorker() {}
void Execute() {
bcrypt_gensalt(minor_ver, rounds, (u_int8_t *)&seed[0], salt);
}
void OnOK() {
Napi::HandleScope scope(Env());
Callback().Call({Env().Undefined(), Napi::String::New(Env(), salt)});
}
private:
std::string seed;
ssize_t rounds;
char minor_ver;
char salt[_SALT_LEN];
};
Napi::Value GenerateSalt(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (info.Length() < 4) {
throw Napi::TypeError::New(env, "4 arguments expected");
}
if (!info[0].IsString()) {
throw Napi::TypeError::New(env, "First argument must be a string");
}
if (!info[2].IsBuffer() || (info[2].As<Napi::Buffer<char>>()).Length() != 16) {
throw Napi::TypeError::New(env, "Second argument must be a 16 byte Buffer");
}
const char minor_ver = ToCharVersion(info[0].As<Napi::String>());
const int32_t rounds = info[1].As<Napi::Number>();
Napi::Buffer<char> seed = info[2].As<Napi::Buffer<char>>();
Napi::Function callback = info[3].As<Napi::Function>();
SaltAsyncWorker* saltWorker = new SaltAsyncWorker(callback, std::string(seed.Data(), 16), rounds, minor_ver);
saltWorker->Queue();
return env.Undefined();
}
Napi::Value GenerateSaltSync(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (info.Length() < 3) {
throw Napi::TypeError::New(env, "3 arguments expected");
}
if (!info[0].IsString()) {
throw Napi::TypeError::New(env, "First argument must be a string");
}
if (!info[2].IsBuffer() || (info[2].As<Napi::Buffer<char>>()).Length() != 16) {
throw Napi::TypeError::New(env, "Third argument must be a 16 byte Buffer");
}
const char minor_ver = ToCharVersion(info[0].As<Napi::String>());
const int32_t rounds = info[1].As<Napi::Number>();
Napi::Buffer<u_int8_t> buffer = info[2].As<Napi::Buffer<u_int8_t>>();
u_int8_t* seed = (u_int8_t*) buffer.Data();
char salt[_SALT_LEN];
bcrypt_gensalt(minor_ver, rounds, seed, salt);
return Napi::String::New(env, salt, strlen(salt));
}
inline std::string BufferToString(const Napi::Buffer<char> &buf) {
return std::string(buf.Data(), buf.Length());
}
/* ENCRYPT DATA - USED TO BE HASHPW */
class EncryptAsyncWorker : public Napi::AsyncWorker {
public:
EncryptAsyncWorker(const Napi::Function& callback, const std::string& input, const std::string& salt)
: Napi::AsyncWorker(callback, "bcrypt:EncryptAsyncWorker"), input(input), salt(salt) {
}
~EncryptAsyncWorker() {}
void Execute() {
if (!(ValidateSalt(salt.c_str()))) {
SetError("Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue");
}
bcrypt(input.c_str(), input.length(), salt.c_str(), bcrypted);
}
void OnOK() {
Napi::HandleScope scope(Env());
Callback().Call({Env().Undefined(),Napi::String::New(Env(), bcrypted)});
}
private:
std::string input;
std::string salt;
char bcrypted[_PASSWORD_LEN];
};
Napi::Value Encrypt(const Napi::CallbackInfo& info) {
if (info.Length() < 3) {
throw Napi::TypeError::New(info.Env(), "3 arguments expected");
}
std::string data = info[0].IsBuffer()
? BufferToString(info[0].As<Napi::Buffer<char>>())
: info[0].As<Napi::String>();
std::string salt = info[1].As<Napi::String>();
Napi::Function callback = info[2].As<Napi::Function>();
EncryptAsyncWorker* encryptWorker = new EncryptAsyncWorker(callback, data, salt);
encryptWorker->Queue();
return info.Env().Undefined();
}
Napi::Value EncryptSync(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (info.Length() < 2) {
throw Napi::TypeError::New(info.Env(), "2 arguments expected");
}
std::string data = info[0].IsBuffer()
? BufferToString(info[0].As<Napi::Buffer<char>>())
: info[0].As<Napi::String>();
std::string salt = info[1].As<Napi::String>();
if (!(ValidateSalt(salt.c_str()))) {
throw Napi::Error::New(env, "Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue");
}
char bcrypted[_PASSWORD_LEN];
bcrypt(data.c_str(), data.length(), salt.c_str(), bcrypted);
return Napi::String::New(env, bcrypted, strlen(bcrypted));
}
/* COMPARATOR */
inline bool CompareStrings(const char* s1, const char* s2) {
return strcmp(s1, s2) == 0;
}
class CompareAsyncWorker : public Napi::AsyncWorker {
public:
CompareAsyncWorker(const Napi::Function& callback, const std::string& input, const std::string& encrypted)
: Napi::AsyncWorker(callback, "bcrypt:CompareAsyncWorker"), input(input), encrypted(encrypted) {
result = false;
}
~CompareAsyncWorker() {}
void Execute() {
char bcrypted[_PASSWORD_LEN];
if (ValidateSalt(encrypted.c_str())) {
bcrypt(input.c_str(), input.length(), encrypted.c_str(), bcrypted);
result = CompareStrings(bcrypted, encrypted.c_str());
}
}
void OnOK() {
Napi::HandleScope scope(Env());
Callback().Call({Env().Undefined(), Napi::Boolean::New(Env(), result)});
}
private:
std::string input;
std::string encrypted;
bool result;
};
Napi::Value Compare(const Napi::CallbackInfo& info) {
if (info.Length() < 3) {
throw Napi::TypeError::New(info.Env(), "3 arguments expected");
}
std::string input = info[0].IsBuffer()
? BufferToString(info[0].As<Napi::Buffer<char>>())
: info[0].As<Napi::String>();
std::string encrypted = info[1].As<Napi::String>();
Napi::Function callback = info[2].As<Napi::Function>();
CompareAsyncWorker* compareWorker = new CompareAsyncWorker(callback, input, encrypted);
compareWorker->Queue();
return info.Env().Undefined();
}
Napi::Value CompareSync(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (info.Length() < 2) {
throw Napi::TypeError::New(info.Env(), "2 arguments expected");
}
std::string pw = info[0].IsBuffer()
? BufferToString(info[0].As<Napi::Buffer<char>>())
: info[0].As<Napi::String>();
std::string hash = info[1].As<Napi::String>();
char bcrypted[_PASSWORD_LEN];
if (ValidateSalt(hash.c_str())) {
bcrypt(pw.c_str(), pw.length(), hash.c_str(), bcrypted);
return Napi::Boolean::New(env, CompareStrings(bcrypted, hash.c_str()));
} else {
return Napi::Boolean::New(env, false);
}
}
Napi::Value GetRounds(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
if (info.Length() < 1) {
throw Napi::TypeError::New(env, "1 argument expected");
}
std::string hash = info[0].As<Napi::String>();
u_int32_t rounds;
if (!(rounds = bcrypt_get_rounds(hash.c_str()))) {
throw Napi::Error::New(env, "invalid hash provided");
}
return Napi::Number::New(env, rounds);
}
} // anonymous namespace
Napi::Object init(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, "gen_salt_sync"), Napi::Function::New(env, GenerateSaltSync));
exports.Set(Napi::String::New(env, "encrypt_sync"), Napi::Function::New(env, EncryptSync));
exports.Set(Napi::String::New(env, "compare_sync"), Napi::Function::New(env, CompareSync));
exports.Set(Napi::String::New(env, "get_rounds"), Napi::Function::New(env, GetRounds));
exports.Set(Napi::String::New(env, "gen_salt"), Napi::Function::New(env, GenerateSalt));
exports.Set(Napi::String::New(env, "encrypt"), Napi::Function::New(env, Encrypt));
exports.Set(Napi::String::New(env, "compare"), Napi::Function::New(env, Compare));
return exports;
}
NODE_API_MODULE(NODE_GYP_MODULE_NAME, init)
/* $OpenBSD: blowfish.c,v 1.18 2004/11/02 17:23:26 hshoexer Exp $ */
/*
* Blowfish block cipher for OpenBSD
* Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
* All rights reserved.
*
* Implementation advice by David Mazieres <dm@lcs.mit.edu>.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Niels Provos.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This code is derived from section 14.3 and the given source
* in section V of Applied Cryptography, second edition.
* Blowfish is an unpatented fast block cipher designed by
* Bruce Schneier.
*/
#include "node_blf.h"
#undef inline
#ifdef __GNUC__
#define inline __inline
#else /* !__GNUC__ */
#define inline
#endif /* !__GNUC__ */
/* Function for Feistel Networks */
#define F(s, x) ((((s)[ (((x)>>24)&0xFF)] \
+ (s)[0x100 + (((x)>>16)&0xFF)]) \
^ (s)[0x200 + (((x)>> 8)&0xFF)]) \
+ (s)[0x300 + ( (x) &0xFF)])
#define BLFRND(s,p,i,j,n) (i ^= F(s,j) ^ (p)[n])
void
Blowfish_encipher(blf_ctx *c, u_int32_t *xl, u_int32_t *xr)
{
u_int32_t Xl;
u_int32_t Xr;
u_int32_t *s = c->S[0];
u_int32_t *p = c->P;
Xl = *xl;
Xr = *xr;
Xl ^= p[0];
BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2);
BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4);
BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6);
BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8);
BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10);
BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12);
BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14);
BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16);
*xl = Xr ^ p[17];
*xr = Xl;
}
void
Blowfish_decipher(blf_ctx *c, u_int32_t *xl, u_int32_t *xr)
{
u_int32_t Xl;
u_int32_t Xr;
u_int32_t *s = c->S[0];
u_int32_t *p = c->P;
Xl = *xl;
Xr = *xr;
Xl ^= p[17];
BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15);
BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13);
BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11);
BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9);
BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7);
BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5);
BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3);
BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1);
*xl = Xr ^ p[0];
*xr = Xl;
}
void
Blowfish_initstate(blf_ctx *c)
{
/* P-box and S-box tables initialized with digits of Pi */
static const blf_ctx initstate =
{ {
{
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a},
{
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7},
{
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0},
{
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}
},
{
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
0x9216d5d9, 0x8979fb1b
} };
*c = initstate;
}
u_int32_t
Blowfish_stream2word(const u_int8_t *data, u_int16_t databytes,
u_int16_t *current)
{
u_int8_t i;
u_int16_t j;
u_int32_t temp;
temp = 0x00000000;
j = *current;
for (i = 0; i < 4; i++, j++) {
if (j >= databytes)
j = 0;
temp = (temp << 8) | data[j];
}
*current = j;
return temp;
}
void
Blowfish_expand0state(blf_ctx *c, const u_int8_t *key, u_int16_t keybytes)
{
u_int16_t i;
u_int16_t j;
u_int16_t k;
u_int32_t temp;
u_int32_t datal;
u_int32_t datar;
j = 0;
for (i = 0; i < BLF_N + 2; i++) {
/* Extract 4 int8 to 1 int32 from keystream */
temp = Blowfish_stream2word(key, keybytes, &j);
c->P[i] = c->P[i] ^ temp;
}
j = 0;
datal = 0x00000000;
datar = 0x00000000;
for (i = 0; i < BLF_N + 2; i += 2) {
Blowfish_encipher(c, &datal, &datar);
c->P[i] = datal;
c->P[i + 1] = datar;
}
for (i = 0; i < 4; i++) {
for (k = 0; k < 256; k += 2) {
Blowfish_encipher(c, &datal, &datar);
c->S[i][k] = datal;
c->S[i][k + 1] = datar;
}
}
}
void
Blowfish_expandstate(blf_ctx *c, const u_int8_t *data, u_int16_t databytes,
const u_int8_t *key, u_int16_t keybytes)
{
u_int16_t i;
u_int16_t j;
u_int16_t k;
u_int32_t temp;
u_int32_t datal;
u_int32_t datar;
j = 0;
for (i = 0; i < BLF_N + 2; i++) {
/* Extract 4 int8 to 1 int32 from keystream */
temp = Blowfish_stream2word(key, keybytes, &j);
c->P[i] = c->P[i] ^ temp;
}
j = 0;
datal = 0x00000000;
datar = 0x00000000;
for (i = 0; i < BLF_N + 2; i += 2) {
datal ^= Blowfish_stream2word(data, databytes, &j);
datar ^= Blowfish_stream2word(data, databytes, &j);
Blowfish_encipher(c, &datal, &datar);
c->P[i] = datal;
c->P[i + 1] = datar;
}
for (i = 0; i < 4; i++) {
for (k = 0; k < 256; k += 2) {
datal ^= Blowfish_stream2word(data, databytes, &j);
datar ^= Blowfish_stream2word(data, databytes, &j);
Blowfish_encipher(c, &datal, &datar);
c->S[i][k] = datal;
c->S[i][k + 1] = datar;
}
}
}
void
blf_key(blf_ctx *c, const u_int8_t *k, u_int16_t len)
{
/* Initialize S-boxes and subkeys with Pi */
Blowfish_initstate(c);
/* Transform S-boxes and subkeys with key */
Blowfish_expand0state(c, k, len);
}
void
blf_enc(blf_ctx *c, u_int32_t *data, u_int16_t blocks)
{
u_int32_t *d;
u_int16_t i;
d = data;
for (i = 0; i < blocks; i++) {
Blowfish_encipher(c, d, d + 1);
d += 2;
}
}
void
blf_dec(blf_ctx *c, u_int32_t *data, u_int16_t blocks)
{
u_int32_t *d;
u_int16_t i;
d = data;
for (i = 0; i < blocks; i++) {
Blowfish_decipher(c, d, d + 1);
d += 2;
}
}
void
blf_ecb_encrypt(blf_ctx *c, u_int8_t *data, u_int32_t len)
{
u_int32_t l, r;
u_int32_t i;
for (i = 0; i < len; i += 8) {
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
Blowfish_encipher(c, &l, &r);
data[0] = l >> 24 & 0xff;
data[1] = l >> 16 & 0xff;
data[2] = l >> 8 & 0xff;
data[3] = l & 0xff;
data[4] = r >> 24 & 0xff;
data[5] = r >> 16 & 0xff;
data[6] = r >> 8 & 0xff;
data[7] = r & 0xff;
data += 8;
}
}
void
blf_ecb_decrypt(blf_ctx *c, u_int8_t *data, u_int32_t len)
{
u_int32_t l, r;
u_int32_t i;
for (i = 0; i < len; i += 8) {
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
Blowfish_decipher(c, &l, &r);
data[0] = l >> 24 & 0xff;
data[1] = l >> 16 & 0xff;
data[2] = l >> 8 & 0xff;
data[3] = l & 0xff;
data[4] = r >> 24 & 0xff;
data[5] = r >> 16 & 0xff;
data[6] = r >> 8 & 0xff;
data[7] = r & 0xff;
data += 8;
}
}
void
blf_cbc_encrypt(blf_ctx *c, u_int8_t *iv, u_int8_t *data, u_int32_t len)
{
u_int32_t l, r;
u_int32_t i, j;
for (i = 0; i < len; i += 8) {
for (j = 0; j < 8; j++)
data[j] ^= iv[j];
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
Blowfish_encipher(c, &l, &r);
data[0] = l >> 24 & 0xff;
data[1] = l >> 16 & 0xff;
data[2] = l >> 8 & 0xff;
data[3] = l & 0xff;
data[4] = r >> 24 & 0xff;
data[5] = r >> 16 & 0xff;
data[6] = r >> 8 & 0xff;
data[7] = r & 0xff;
iv = data;
data += 8;
}
}
void
blf_cbc_decrypt(blf_ctx *c, u_int8_t *iva, u_int8_t *data, u_int32_t len)
{
u_int32_t l, r;
u_int8_t *iv;
u_int32_t i, j;
iv = data + len - 16;
data = data + len - 8;
for (i = len - 8; i >= 8; i -= 8) {
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
Blowfish_decipher(c, &l, &r);
data[0] = l >> 24 & 0xff;
data[1] = l >> 16 & 0xff;
data[2] = l >> 8 & 0xff;
data[3] = l & 0xff;
data[4] = r >> 24 & 0xff;
data[5] = r >> 16 & 0xff;
data[6] = r >> 8 & 0xff;
data[7] = r & 0xff;
for (j = 0; j < 8; j++)
data[j] ^= iv[j];
iv -= 8;
data -= 8;
}
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
Blowfish_decipher(c, &l, &r);
data[0] = l >> 24 & 0xff;
data[1] = l >> 16 & 0xff;
data[2] = l >> 8 & 0xff;
data[3] = l & 0xff;
data[4] = r >> 24 & 0xff;
data[5] = r >> 16 & 0xff;
data[6] = r >> 8 & 0xff;
data[7] = r & 0xff;
for (j = 0; j < 8; j++)
data[j] ^= iva[j];
}
#if 0
void
report(u_int32_t data[], u_int16_t len)
{
u_int16_t i;
for (i = 0; i < len; i += 2)
printf("Block %0hd: %08lx %08lx.\n",
i / 2, data[i], data[i + 1]);
}
void
main(void)
{
blf_ctx c;
char key[] = "AAAAA";
char key2[] = "abcdefghijklmnopqrstuvwxyz";
u_int32_t data[10];
u_int32_t data2[] =
{0x424c4f57l, 0x46495348l};
u_int16_t i;
/* First test */
for (i = 0; i < 10; i++)
data[i] = i;
blf_key(&c, (u_int8_t *) key, 5);
blf_enc(&c, data, 5);
blf_dec(&c, data, 1);
blf_dec(&c, data + 2, 4);
printf("Should read as 0 - 9.\n");
report(data, 10);
/* Second test */
blf_key(&c, (u_int8_t *) key2, strlen(key2));
blf_enc(&c, data2, 1);
printf("\nShould read as: 0x324ed0fe 0xf413a203.\n");
report(data2, 2);
blf_dec(&c, data2, 1);
report(data2, 2);
}
#endif
/* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */
/*
* Blowfish - a fast block cipher designed by Bruce Schneier
*
* Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Niels Provos.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _NODE_BLF_H_
#define _NODE_BLF_H_
#include <sys/types.h>
/* Solaris compatibility */
#ifdef __sun
#define u_int8_t uint8_t
#define u_int16_t uint16_t
#define u_int32_t uint32_t
#define u_int64_t uint64_t
#endif
#ifdef _WIN32
#define u_int8_t unsigned __int8
#define u_int16_t unsigned __int16
#define u_int32_t unsigned __int32
#define u_int64_t unsigned __int64
#endif
/* Windows ssize_t compatibility */
#if defined(_WIN32) || defined(_WIN64)
# if defined(_WIN64)
typedef __int64 LONG_PTR;
# else
typedef long LONG_PTR;
# endif
typedef LONG_PTR SSIZE_T;
typedef SSIZE_T ssize_t;
#endif
/* z/OS compatibility */
#ifdef __MVS__
typedef unsigned char u_int8_t;
typedef unsigned short u_int16_t;
typedef unsigned int u_int32_t;
typedef unsigned long long u_int64_t;
#endif
#define BCRYPT_VERSION '2'
#define BCRYPT_MAXSALT 16 /* Precomputation is just so nice */
#define BCRYPT_BLOCKS 6 /* Ciphertext blocks */
#define BCRYPT_MINROUNDS 16 /* we have log2(rounds) in salt */
/* Schneier specifies a maximum key length of 56 bytes.
* This ensures that every key bit affects every cipher
* bit. However, the subkeys can hold up to 72 bytes.
* Warning: For normal blowfish encryption only 56 bytes
* of the key affect all cipherbits.
*/
#define BLF_N 16 /* Number of Subkeys */
#define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */
#define BLF_MAXUTILIZED ((BLF_N+2)*4) /* 576 bits */
#define _PASSWORD_LEN 128 /* max length, not counting NUL */
#define _SALT_LEN 32 /* max length */
/* Blowfish context */
typedef struct BlowfishContext {
u_int32_t S[4][256]; /* S-Boxes */
u_int32_t P[BLF_N + 2]; /* Subkeys */
} blf_ctx;
/* Raw access to customized Blowfish
* blf_key is just:
* Blowfish_initstate( state )
* Blowfish_expand0state( state, key, keylen )
*/
void Blowfish_encipher(blf_ctx *, u_int32_t *, u_int32_t *);
void Blowfish_decipher(blf_ctx *, u_int32_t *, u_int32_t *);
void Blowfish_initstate(blf_ctx *);
void Blowfish_expand0state(blf_ctx *, const u_int8_t *, u_int16_t);
void Blowfish_expandstate
(blf_ctx *, const u_int8_t *, u_int16_t, const u_int8_t *, u_int16_t);
/* Standard Blowfish */
void blf_key(blf_ctx *, const u_int8_t *, u_int16_t);
void blf_enc(blf_ctx *, u_int32_t *, u_int16_t);
void blf_dec(blf_ctx *, u_int32_t *, u_int16_t);
void blf_ecb_encrypt(blf_ctx *, u_int8_t *, u_int32_t);
void blf_ecb_decrypt(blf_ctx *, u_int8_t *, u_int32_t);
void blf_cbc_encrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t);
void blf_cbc_decrypt(blf_ctx *, u_int8_t *, u_int8_t *, u_int32_t);
/* Converts u_int8_t to u_int32_t */
u_int32_t Blowfish_stream2word(const u_int8_t *, u_int16_t , u_int16_t *);
/* bcrypt functions*/
void bcrypt_gensalt(char, u_int8_t, u_int8_t*, char *);
void bcrypt(const char *, size_t key_len, const char *, char *);
void encode_salt(char *, u_int8_t *, char, u_int16_t, u_int8_t);
u_int32_t bcrypt_get_rounds(const char *);
#endif
#!/bin/sh
set -xe
echo "Running on $(node -v)"
# Cleanup
rm -rf node_modules build-tmp-* lib/binding
# Install build dependencies
if [ -f /etc/alpine-release ]; then
apk add --no-cache --virtual .build-deps make gcc g++ python3
fi
su node -c "npm test; npx node-pre-gyp package"
const bcrypt = require('../bcrypt');
test('salt_length', done => {
expect.assertions(1);
bcrypt.genSalt(10, function (err, salt) {
expect(salt).toHaveLength(29);
done();
});
})
test('salt_only_cb', () => {
expect.assertions(1);
expect(() => {
bcrypt.genSalt((err, salt) => {
});
}).not.toThrow();
})
test('salt_rounds_is_string_number', done => {
expect.assertions(2);
bcrypt.genSalt('10', void 0, function (err, salt) {
expect(err instanceof Error).toBe(true)
expect(err.message).toBe('rounds must be a number')
done();
});
})
test('salt_rounds_is_string_non_number', done => {
expect.assertions(2);
bcrypt.genSalt('z', function (err, salt) {
expect(err instanceof Error).toBe(true)
expect(err.message).toBe('rounds must be a number')
done();
});
})
test('salt_minor', done => {
expect.assertions(3);
bcrypt.genSalt(10, 'a', function (err, value) {
expect(value).toHaveLength(29);
const [_, minor, salt] = value.split('$');
expect(minor).toEqual('2a');
expect(salt).toEqual('10');
done();
});
})
test('salt_minor_b', done => {
expect.assertions(3);
bcrypt.genSalt(10, 'b', function (err, value) {
expect(value).toHaveLength(29);
const [_, minor, salt] = value.split('$');
expect(minor).toEqual('2b');
expect(salt).toEqual('10');
done();
});
})
test('hash', done => {
expect.assertions(2);
bcrypt.genSalt(10, function (err, salt) {
bcrypt.hash('password', salt, function (err, res) {
expect(res).toBeDefined();
expect(err).toBeUndefined();
done();
});
});
})
test('hash_rounds', done => {
expect.assertions(1);
bcrypt.hash('bacon', 8, function (err, hash) {
expect(bcrypt.getRounds(hash)).toEqual(8);
done();
});
})
test('hash_empty_strings', done => {
expect.assertions(1);
bcrypt.genSalt(10, function (err, salt) {
bcrypt.hash('', salt, function (err, res) {
expect(res).toBeDefined();
done();
});
});
})
test('hash_fails_with_empty_salt', done => {
expect.assertions(1);
bcrypt.hash('', '', function (err, res) {
expect(err.message).toBe('Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue')
done();
});
})
test('hash_no_params', done => {
expect.assertions(1);
bcrypt.hash(function (err, hash) {
expect(err.message).toBe('data must be a string or Buffer and salt must either be a salt string or a number of rounds')
done();
});
})
test('hash_one_param', done => {
expect.assertions(1);
bcrypt.hash('password', function (err, hash) {
expect(err.message).toBe('data must be a string or Buffer and salt must either be a salt string or a number of rounds');
done();
});
})
test('hash_salt_validity', done => {
expect.assertions(2);
bcrypt.hash('password', '$2a$10$somesaltyvaluertsetrse', function (err, enc) {
expect(err).toBeUndefined();
bcrypt.hash('password', 'some$value', function (err, enc) {
expect(err.message).toBe("Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue");
done();
});
});
})
test('verify_salt', done => {
expect.assertions(2);
bcrypt.genSalt(10, function (err, value) {
const [_, version, rounds] = value.split('$');
expect(version).toEqual('2b');
expect(rounds).toEqual('10');
done();
});
})
test('verify_salt_min_rounds', done => {
expect.assertions(2);
bcrypt.genSalt(1, function (err, value) {
const [_, version, rounds] = value.split('$');
expect(version).toEqual('2b');
expect(rounds).toEqual('04');
done();
});
})
test('verify_salt_max_rounds', done => {
expect.assertions(2);
bcrypt.genSalt(100, function (err, value) {
const [_, version, rounds] = value.split('$');
expect(version).toEqual('2b');
expect(rounds).toEqual('31');
done();
});
})
test('hash_compare', done => {
expect.assertions(2);
bcrypt.genSalt(10, function (err, salt) {
bcrypt.hash("test", salt, function (err, hash) {
bcrypt.compare("test", hash, function (err, res) {
expect(hash).toBeDefined();
bcrypt.compare("blah", hash, function (err, res) {
expect(res).toBe(false);
done();
});
});
});
});
})
test('hash_compare_empty_strings', done => {
expect.assertions(2);
const hash = bcrypt.hashSync("test", bcrypt.genSaltSync(10));
bcrypt.compare("", hash, function (err, res) {
expect(res).toEqual(false)
bcrypt.compare("", "", function (err, res) {
expect(res).toEqual(false);
done();
});
});
})
test('hash_compare_invalid_strings', done => {
expect.assertions(2);
const fullString = 'envy1362987212538';
const hash = '$2a$10$XOPbrlUPQdwdJUpSrIF6X.LbE14qsMmKGhM1A8W9iqaG3vv1BD7WC';
const wut = ':';
bcrypt.compare(fullString, hash, function (err, res) {
expect(res).toBe(true);
bcrypt.compare(fullString, wut, function (err, res) {
expect(res).toBe(false);
done();
});
});
})
test('compare_no_params', done => {
expect.assertions(1);
bcrypt.compare(function (err, hash) {
expect(err.message).toBe('data and hash arguments required');
done();
});
})
test('hash_compare_one_param', done => {
expect.assertions(1);
bcrypt.compare('password', function (err, hash) {
expect(err.message).toBe('data and hash arguments required');
done();
});
})
const bcrypt = require('../bcrypt');
// some tests were adapted from https://github.com/riverrun/bcrypt_elixir/blob/master/test/base_test.exs
// which are under the BSD LICENSE
test('openwall', () => {
expect(bcrypt.hashSync("U*U", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.")).toStrictEqual("$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW");
expect(bcrypt.hashSync("U*U*", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.")).toStrictEqual("$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK");
expect(bcrypt.hashSync("U*U*U", "$2a$05$XXXXXXXXXXXXXXXXXXXXXO")).toStrictEqual("$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a");
expect(bcrypt.hashSync("", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.")).toStrictEqual("$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy");
expect(bcrypt.hashSync("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", "$2a$05$abcdefghijklmnopqrstuu")).toStrictEqual("$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui");
})
test('openbsd', () => {
expect(bcrypt.hashSync("000000000000000000000000000000000000000000000000000000000000000000000000", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.")).toStrictEqual("$2a$05$CCCCCCCCCCCCCCCCCCCCC.6.O1dLNbjod2uo0DVcW.jHucKbPDdHS")
expect(bcrypt.hashSync("000000000000000000000000000000000000000000000000000000000000000000000000", "$2b$05$CCCCCCCCCCCCCCCCCCCCC.")).toStrictEqual("$2b$05$CCCCCCCCCCCCCCCCCCCCC.6.O1dLNbjod2uo0DVcW.jHucKbPDdHS")
})
test('long_passwords', () => {
// bcrypt wrap-around bug in $2a$
expect(bcrypt.hashSync("012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.")).toStrictEqual("$2a$05$CCCCCCCCCCCCCCCCCCCCC.6.O1dLNbjod2uo0DVcW.jHucKbPDdHS")
expect(bcrypt.hashSync("01XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "$2a$05$CCCCCCCCCCCCCCCCCCCCC.")).toStrictEqual("$2a$05$CCCCCCCCCCCCCCCCCCCCC.6.O1dLNbjod2uo0DVcW.jHucKbPDdHS")
// tests for $2b$ which fixes wrap-around bugs
expect(bcrypt.hashSync("012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234", "$2b$05$CCCCCCCCCCCCCCCCCCCCC.")).toStrictEqual("$2b$05$CCCCCCCCCCCCCCCCCCCCC.XxrQqgBi/5Sxuq9soXzDtjIZ7w5pMfK")
expect(bcrypt.hashSync("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345", "$2b$05$CCCCCCCCCCCCCCCCCCCCC.")).toStrictEqual("$2b$05$CCCCCCCCCCCCCCCCCCCCC.XxrQqgBi/5Sxuq9soXzDtjIZ7w5pMfK")
})
test('embedded_nulls', () => {
expect(bcrypt.hashSync("Passw\0rd123", "$2b$05$CCCCCCCCCCCCCCCCCCCCC.")).toStrictEqual("$2b$05$CCCCCCCCCCCCCCCCCCCCC.VHy/kzL4sCcX3Ib3wN5rNGiRt.TpfxS")
expect(bcrypt.hashSync("Passw\0 you can literally write anything after the NUL character", "$2b$05$CCCCCCCCCCCCCCCCCCCCC.")).toStrictEqual("$2b$05$CCCCCCCCCCCCCCCCCCCCC.4vJLJQ6nZ/70INTjjSZWQ0iyUek92tu")
expect(bcrypt.hashSync(Buffer.from("Passw\0 you can literally write anything after the NUL character"), "$2b$05$CCCCCCCCCCCCCCCCCCCCC.")).toStrictEqual("$2b$05$CCCCCCCCCCCCCCCCCCCCC.4vJLJQ6nZ/70INTjjSZWQ0iyUek92tu")
})
test('shorten_salt_to_128_bits', () => {
expect(bcrypt.hashSync("test", "$2a$10$1234567899123456789012")).toStrictEqual("$2a$10$123456789912345678901u.OtL1A1eGK5wmvBKUDYKvuVKI7h2XBu")
expect(bcrypt.hashSync("U*U*", "$2a$05$CCCCCCCCCCCCCCCCCCCCCh")).toStrictEqual("$2a$05$CCCCCCCCCCCCCCCCCCCCCeUQ7VjYZ2hd4bLYZdhuPpZMUpEUJDw1S")
expect(bcrypt.hashSync("U*U*", "$2a$05$CCCCCCCCCCCCCCCCCCCCCM")).toStrictEqual("$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK")
expect(bcrypt.hashSync("U*U*", "$2a$05$CCCCCCCCCCCCCCCCCCCCCA")).toStrictEqual("$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK")
})
test('consistency', () => {
expect(bcrypt.hashSync("ππππππππ", "$2a$10$.TtQJ4Jr6isd4Hp.mVfZeu")).toStrictEqual("$2a$10$.TtQJ4Jr6isd4Hp.mVfZeuh6Gws4rOQ/vdBczhDx.19NFK0Y84Dle")
expect(bcrypt.hashSync("p@5sw0rd", "$2b$12$zQ4CooEXdGqcwi0PHsgc8e")).toStrictEqual("$2b$12$zQ4CooEXdGqcwi0PHsgc8eAf0DLXE/XHoBE8kCSGQ97rXwuClaPam")
expect(bcrypt.hashSync("C'est bon, la vie!", "$2b$12$cbo7LZ.wxgW4yxAA5Vqlv.")).toStrictEqual("$2b$12$cbo7LZ.wxgW4yxAA5Vqlv.KR6QFPt4qCdc9RYJNXxa/rbUOp.1sw.")
expect(bcrypt.hashSync("ἓν οἶδα ὅτι οὐδὲν οἶδα", "$2b$12$LeHKWR2bmrazi/6P22Jpau")).toStrictEqual("$2b$12$LeHKWR2bmrazi/6P22JpauX5my/eKwwKpWqL7L5iEByBnxNc76FRW")
expect(bcrypt.hashSync(Buffer.from("ἓν οἶδα ὅτι οὐδὲν οἶδα"), "$2b$12$LeHKWR2bmrazi/6P22Jpau")).toStrictEqual("$2b$12$LeHKWR2bmrazi/6P22JpauX5my/eKwwKpWqL7L5iEByBnxNc76FRW")
})
const bcrypt = require('../bcrypt');
const promises = require('../promises');
test('salt_returns_promise_on_no_args', () => {
// make sure test passes with non-native implementations such as bluebird
// http://stackoverflow.com/questions/27746304/how-do-i-tell-if-an-object-is-a-promise
expect(typeof bcrypt.genSalt().then).toEqual('function')
})
test('salt_returns_promise_on_null_callback', () => {
expect(typeof bcrypt.genSalt(13, null, null).then).toEqual('function')
})
test('salt_length', () => {
return expect(bcrypt.genSalt(10)).resolves.toHaveLength(29);
})
test('salt_rounds_is_string_number', () => {
return expect(bcrypt.genSalt('10')).rejects.toThrow('rounds must be a number');
})
test('salt_rounds_is_string_non_number', () => {
return expect(bcrypt.genSalt('b')).rejects.toThrow('rounds must be a number');
})
test('hash_returns_promise_on_null_callback', () => {
expect(typeof bcrypt.hash('password', 10, null).then).toStrictEqual('function')
})
test('hash', () => {
return expect(bcrypt.genSalt(10)
.then(salt => bcrypt.hash('password', salt))).resolves.toBeDefined()
})
test('hash_rounds', () => {
return bcrypt.hash('bacon', 8).then(hash => {
expect(bcrypt.getRounds(hash)).toStrictEqual(8)
});
})
test('hash_empty_strings', () => {
expect.assertions(2);
return Promise.all([
expect(bcrypt.genSalt(10)
.then(salt => bcrypt.hash('', salt)))
.resolves.toBeDefined(),
expect(bcrypt.hash('', '')).rejects.toThrow(''),
]);
})
test('hash_no_params', () => {
expect.assertions(1);
return expect(bcrypt.hash()).rejects.toThrow('data and salt arguments required');
})
test('hash_one_param', () => {
return expect(bcrypt.hash('password')).rejects.toThrow('data and salt arguments required');
})
test('hash_salt_validity', () => {
expect.assertions(2);
return Promise.all(
[
expect(bcrypt.hash('password', '$2a$10$somesaltyvaluertsetrse')).resolves.toBeDefined(),
expect(bcrypt.hash('password', 'some$value')).rejects.toThrow("Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue")
]);
})
test('verify_salt', () => {
expect.assertions(2);
return bcrypt.genSalt(10).then(result => {
const [_, version, salt] = result.split('$');
expect(version).toEqual('2b')
expect(salt).toEqual('10')
});
})
test('verify_salt_min_rounds', () => {
expect.assertions(2);
return bcrypt.genSalt(1).then(value => {
const [_, version, rounds] = value.split('$');
expect(version).toEqual('2b');
expect(rounds).toEqual('04');
});
})
test('verify_salt_max_rounds', () => {
expect.assertions(2);
return bcrypt.genSalt(100).then(value => {
const [_, version, rounds] = value.split('$');
expect(version).toEqual('2b');
expect(rounds).toEqual('31');
});
})
test('hash_compare_returns_promise_on_null_callback', () => {
expect(typeof bcrypt.compare('password', 'something', null).then).toStrictEqual('function')
})
test('hash_compare', () => {
expect.assertions(3);
return bcrypt.genSalt(10).then(function (salt) {
expect(salt).toHaveLength(29);
return bcrypt.hash("test", salt);
}).then(hash => Promise.all(
[
expect(bcrypt.compare("test", hash)).resolves.toEqual(true),
expect(bcrypt.compare("blah", hash)).resolves.toEqual(false)
]));
})
test('hash_compare_empty_strings', () => {
expect.assertions(2);
const hash = bcrypt.hashSync("test", bcrypt.genSaltSync(10));
return Promise.all([
expect(bcrypt.compare("", hash)).resolves.toEqual(false),
expect(bcrypt.compare("", "")).resolves.toEqual(false)
]);
})
test('hash_compare_invalid_strings', () => {
const fullString = 'envy1362987212538';
const hash = '$2a$10$XOPbrlUPQdwdJUpSrIF6X.LbE14qsMmKGhM1A8W9iqaG3vv1BD7WC';
const wut = ':';
return Promise.all([
expect(bcrypt.compare(fullString, hash)).resolves.toEqual(true),
expect(bcrypt.compare(fullString, wut)).resolves.toEqual(false),
]);
})
test('hash_compare_no_params', () => {
expect.assertions(1);
return expect(bcrypt.compare()).rejects.toThrow('data and hash arguments required')
})
test('hash_compare_one_param', () => {
expect.assertions(1);
return expect(bcrypt.compare('password')).rejects.toThrow('data and hash arguments required')
})
test('change_promise_impl_reject', () => {
promises.use({
reject: function () {
return 'mock';
}
});
expect(promises.reject()).toEqual('mock');
// need to reset the promise implementation because of require cache
promises.use(global.Promise);
})
test('change_promise_impl_promise', () => {
promises.use({
reject: function (err) {
expect(err.message).toEqual('fn must be a function');
return 'mock';
}
});
expect(promises.promise('', '', '')).toEqual('mock');
// need to reset the promise implementation because of require cache
promises.use(global.Promise);
})
const bcrypt = require('../bcrypt');
const EXPECTED = 2500; //number of times to iterate these tests.)
test('salt_length', () => {
expect.assertions(EXPECTED);
return Promise.all(Array.from({length: EXPECTED},
() => bcrypt.genSalt(10)
.then(salt => expect(salt).toHaveLength(29))));
})
test('test_hash_length', () => {
expect.assertions(EXPECTED);
const SALT = '$2a$04$TnjywYklQbbZjdjBgBoA4e';
return Promise.all(Array.from({length: EXPECTED},
() => bcrypt.hash('test', SALT)
.then(hash => expect(hash).toHaveLength(60))));
})
test('test_compare', () => {
expect.assertions(EXPECTED);
const HASH = '$2a$04$TnjywYklQbbZjdjBgBoA4e9G7RJt9blgMgsCvUvus4Iv4TENB5nHy';
return Promise.all(Array.from({length: EXPECTED},
() => bcrypt.compare('test', HASH)
.then(match => expect(match).toEqual(true))));
})
test('test_hash_and_compare', () => {
expect.assertions(EXPECTED * 3);
const salt = bcrypt.genSaltSync(4)
return Promise.all(Array.from({length: EXPECTED},
() => {
const password = 'secret' + Math.random();
return bcrypt.hash(password, salt)
.then(hash => {
expect(hash).toHaveLength(60);
const goodCompare = bcrypt.compare(password, hash).then(res => expect(res).toEqual(true));
const badCompare = bcrypt.compare('bad' + password, hash).then(res => expect(res).toEqual(false));
return Promise.all([goodCompare, badCompare]);
});
}));
}, 10000);
const bcrypt = require('../bcrypt')
test('salt_length', () => {
const salt = bcrypt.genSaltSync(13);
expect(salt).toHaveLength(29);
const [_, version, rounds] = salt.split('$');
expect(version).toStrictEqual('2b')
expect(rounds).toStrictEqual('13')
})
test('salt_no_params', () => {
const salt = bcrypt.genSaltSync();
const [_, version, rounds] = salt.split('$');
expect(version).toStrictEqual('2b')
expect(rounds).toStrictEqual('10')
})
test('salt_rounds_is_string_number', () => {
expect(() => bcrypt.genSaltSync('10')).toThrowError('rounds must be a number');
})
test('salt_rounds_is_NaN', () => {
expect(() => bcrypt.genSaltSync('b')).toThrowError("rounds must be a number");
})
test('salt_minor_a', () => {
const salt = bcrypt.genSaltSync(10, 'a');
const [_, version, rounds] = salt.split('$');
expect(version).toStrictEqual('2a')
expect(rounds).toStrictEqual('10')
})
test('salt_minor_b', () => {
const salt = bcrypt.genSaltSync(10, 'b');
const [_, version, rounds] = salt.split('$');
expect(version).toStrictEqual('2b')
expect(rounds).toStrictEqual('10')
})
test('hash', () => {
expect(() => bcrypt.hashSync('password', bcrypt.genSaltSync(10))).not.toThrow()
})
test('hash_rounds', () => {
const hash = bcrypt.hashSync('password', 8);
expect(bcrypt.getRounds(hash)).toStrictEqual(8)
})
test('hash_empty_string', () => {
expect(() => bcrypt.hashSync('', bcrypt.genSaltSync(10))).not.toThrow();
expect(() => bcrypt.hashSync('password', '')).toThrowError('Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue');
expect(() => bcrypt.hashSync('', '')).toThrowError('Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue');
})
test('hash_pw_no_params', () => {
expect(() => bcrypt.hashSync()).toThrow('data and salt arguments required');
})
test('hash_pw_one_param', () => {
expect(() => bcrypt.hashSync('password')).toThrow('data and salt arguments required');
})
test('hash_pw_not_hash_str', () => {
expect(() => bcrypt.hashSync('password', {})).toThrow("data must be a string or Buffer and salt must either be a salt string or a number of rounds")
})
test('hash_salt_validity', () => {
expect(2);
expect(bcrypt.hashSync('password', '$2a$10$somesaltyvaluertsetrse')).toBeDefined()
expect(() => bcrypt.hashSync('password', 'some$value')).toThrow('Invalid salt. Salt must be in the form of: $Vers$log2(NumRounds)$saltvalue')
})
test('verify_salt', () => {
const salt = bcrypt.genSaltSync(10);
const split_salt = salt.split('$');
expect(split_salt[1]).toStrictEqual('2b')
expect(split_salt[2]).toStrictEqual('10')
})
test('verify_salt_min_rounds', () => {
const salt = bcrypt.genSaltSync(1);
const split_salt = salt.split('$');
expect(split_salt[1]).toStrictEqual('2b')
expect(split_salt[2]).toStrictEqual('04')
})
test('verify_salt_max_rounds', () => {
const salt = bcrypt.genSaltSync(100);
const split_salt = salt.split('$');
expect(split_salt[1]).toStrictEqual('2b')
expect(split_salt[2]).toStrictEqual('31')
})
test('hash_compare', () => {
const salt = bcrypt.genSaltSync(10);
expect(29).toStrictEqual(salt.length)
const hash = bcrypt.hashSync("test", salt);
expect(bcrypt.compareSync("test", hash)).toBeDefined()
expect(!(bcrypt.compareSync("blah", hash))).toBeDefined()
})
test('hash_compare_empty_strings', () => {
expect(!(bcrypt.compareSync("", "password"))).toBeDefined()
expect(!(bcrypt.compareSync("", ""))).toBeDefined()
expect(!(bcrypt.compareSync("password", ""))).toBeDefined()
})
test('hash_compare_invalid_strings', () => {
const fullString = 'envy1362987212538';
const hash = '$2a$10$XOPbrlUPQdwdJUpSrIF6X.LbE14qsMmKGhM1A8W9iqaG3vv1BD7WC';
const wut = ':';
expect(bcrypt.compareSync(fullString, hash)).toBe(true);
expect(bcrypt.compareSync(fullString, wut)).toBe(false);
})
test('getRounds', () => {
const hash = bcrypt.hashSync("test", bcrypt.genSaltSync(9));
expect(9).toStrictEqual(bcrypt.getRounds(hash))
})
test('getRounds', () => {
const hash = bcrypt.hashSync("test", bcrypt.genSaltSync(9));
expect(9).toStrictEqual(bcrypt.getRounds(hash))
expect(() => bcrypt.getRounds('')).toThrow("invalid hash provided");
});
[
"3dm",
"3ds",
"3g2",
"3gp",
"7z",
"a",
"aac",
"adp",
"afdesign",
"afphoto",
"afpub",
"ai",
"aif",
"aiff",
"alz",
"ape",
"apk",
"appimage",
"ar",
"arj",
"asf",
"au",
"avi",
"bak",
"baml",
"bh",
"bin",
"bk",
"bmp",
"btif",
"bz2",
"bzip2",
"cab",
"caf",
"cgm",
"class",
"cmx",
"cpio",
"cr2",
"cur",
"dat",
"dcm",
"deb",
"dex",
"djvu",
"dll",
"dmg",
"dng",
"doc",
"docm",
"docx",
"dot",
"dotm",
"dra",
"DS_Store",
"dsk",
"dts",
"dtshd",
"dvb",
"dwg",
"dxf",
"ecelp4800",
"ecelp7470",
"ecelp9600",
"egg",
"eol",
"eot",
"epub",
"exe",
"f4v",
"fbs",
"fh",
"fla",
"flac",
"flatpak",
"fli",
"flv",
"fpx",
"fst",
"fvt",
"g3",
"gh",
"gif",
"graffle",
"gz",
"gzip",
"h261",
"h263",
"h264",
"icns",
"ico",
"ief",
"img",
"ipa",
"iso",
"jar",
"jpeg",
"jpg",
"jpgv",
"jpm",
"jxr",
"key",
"ktx",
"lha",
"lib",
"lvp",
"lz",
"lzh",
"lzma",
"lzo",
"m3u",
"m4a",
"m4v",
"mar",
"mdi",
"mht",
"mid",
"midi",
"mj2",
"mka",
"mkv",
"mmr",
"mng",
"mobi",
"mov",
"movie",
"mp3",
"mp4",
"mp4a",
"mpeg",
"mpg",
"mpga",
"mxu",
"nef",
"npx",
"numbers",
"nupkg",
"o",
"odp",
"ods",
"odt",
"oga",
"ogg",
"ogv",
"otf",
"ott",
"pages",
"pbm",
"pcx",
"pdb",
"pdf",
"pea",
"pgm",
"pic",
"png",
"pnm",
"pot",
"potm",
"potx",
"ppa",
"ppam",
"ppm",
"pps",
"ppsm",
"ppsx",
"ppt",
"pptm",
"pptx",
"psd",
"pya",
"pyc",
"pyo",
"pyv",
"qt",
"rar",
"ras",
"raw",
"resources",
"rgb",
"rip",
"rlc",
"rmf",
"rmvb",
"rpm",
"rtf",
"rz",
"s3m",
"s7z",
"scpt",
"sgi",
"shar",
"snap",
"sil",
"sketch",
"slk",
"smv",
"snk",
"so",
"stl",
"suo",
"sub",
"swf",
"tar",
"tbz",
"tbz2",
"tga",
"tgz",
"thmx",
"tif",
"tiff",
"tlz",
"ttc",
"ttf",
"txz",
"udf",
"uvh",
"uvi",
"uvm",
"uvp",
"uvs",
"uvu",
"viv",
"vob",
"war",
"wav",
"wax",
"wbmp",
"wdp",
"weba",
"webm",
"webp",
"whl",
"wim",
"wm",
"wma",
"wmv",
"wmx",
"woff",
"woff2",
"wrm",
"wvx",
"xbm",
"xif",
"xla",
"xlam",
"xls",
"xlsb",
"xlsm",
"xlsx",
"xlt",
"xltm",
"xltx",
"xm",
"xmind",
"xpi",
"xpm",
"xwd",
"xz",
"z",
"zip",
"zipx"
]
declare const binaryExtensionsJson: readonly string[];
export = binaryExtensionsJson;
/**
List of binary file extensions.
@example
```
import binaryExtensions = require('binary-extensions');
console.log(binaryExtensions);
//=> ['3ds', '3g2', …]
```
*/
declare const binaryExtensions: readonly string[];
export = binaryExtensions;
module.exports = require('./binary-extensions.json');
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
Copyright (c) Paul Miller (https://paulmillr.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
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 OR COPYRIGHT HOLDERS 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.
{
"name": "binary-extensions",
"version": "2.3.0",
"description": "List of binary file extensions",
"license": "MIT",
"repository": "sindresorhus/binary-extensions",
"funding": "https://github.com/sponsors/sindresorhus",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"sideEffects": false,
"engines": {
"node": ">=8"
},
"scripts": {
"test": "xo && ava && tsd"
},
"files": [
"index.js",
"index.d.ts",
"binary-extensions.json",
"binary-extensions.json.d.ts"
],
"keywords": [
"binary",
"extensions",
"extension",
"file",
"json",
"list",
"array"
],
"devDependencies": {
"ava": "^1.4.1",
"tsd": "^0.7.2",
"xo": "^0.24.0"
}
}
# binary-extensions
> List of binary file extensions
The list is just a [JSON file](binary-extensions.json) and can be used anywhere.
## Install
```sh
npm install binary-extensions
```
## Usage
```js
const binaryExtensions = require('binary-extensions');
console.log(binaryExtensions);
//=> ['3ds', '3g2', …]
```
## Related
- [is-binary-path](https://github.com/sindresorhus/is-binary-path) - Check if a filepath is a binary file
- [text-extensions](https://github.com/sindresorhus/text-extensions) - List of text file extensions