mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-30 22:34:10 -05:00
refactor: create cryto utils
This commit is contained in:
parent
4a5116fb5d
commit
87e3faa624
10 changed files with 75 additions and 66 deletions
|
@ -17,13 +17,13 @@ export default function(route: Router, auth: IAuth) {
|
|||
|
||||
route.put('/-/user/:org_couchdb_user/:_rev?/:revision?', function(req: $RequestExtend, res: $Response, next: $NextFunctionVer) {
|
||||
let token = (req.body.name && req.body.password)
|
||||
? auth.aes_encrypt(new Buffer(req.body.name + ':' + req.body.password)).toString('base64')
|
||||
? auth.aesEncrypt(new Buffer(req.body.name + ':' + req.body.password)).toString('base64')
|
||||
: undefined;
|
||||
if (_.isNil(req.remote_user.name) === false) {
|
||||
res.status(201);
|
||||
return next({
|
||||
ok: 'you are authenticated as \'' + req.remote_user.name + '\'',
|
||||
token: token,
|
||||
token,
|
||||
});
|
||||
} else {
|
||||
auth.add_user(req.body.name, req.body.password, function(err, user) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import crypto from 'crypto';
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
validate_name as utilValidateName,
|
||||
|
@ -8,6 +7,7 @@ import {
|
|||
isObject,
|
||||
ErrorCode} from '../lib/utils';
|
||||
import {HEADERS} from '../lib/constants';
|
||||
import {stringToMD5} from '../lib/crypto-utils';
|
||||
import type {$ResponseExtend, $RequestExtend, $NextFunctionVer, IAuth} from '../../types';
|
||||
import type {Config} from '@verdaccio/types';
|
||||
|
||||
|
@ -97,18 +97,6 @@ export function anti_loop(config: Config) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Express doesn't do etags with requests <= 1024b
|
||||
* we use md5 here, it works well on 1k+ bytes, but sucks with fewer data
|
||||
* could improve performance using crc32 after benchmarks.
|
||||
* @param {Object} data
|
||||
* @return {String}
|
||||
*/
|
||||
function md5sum(data) {
|
||||
return crypto.createHash('md5').update(data).digest('hex');
|
||||
}
|
||||
|
||||
|
||||
export function allow(auth: IAuth) {
|
||||
return function(action: string) {
|
||||
return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
|
||||
|
@ -155,7 +143,7 @@ export function allow(auth: IAuth) {
|
|||
|
||||
// don't send etags with errors
|
||||
if (!res.statusCode || (res.statusCode >= 200 && res.statusCode < 300)) {
|
||||
res.header('ETag', '"' + md5sum(body) + '"');
|
||||
res.header('ETag', '"' + stringToMD5(body) + '"');
|
||||
}
|
||||
} else {
|
||||
// send(null), send(204), etc.
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
// @flow
|
||||
|
||||
import {loadPlugin} from '../lib/plugin-loader';
|
||||
import Crypto from 'crypto';
|
||||
import jwt from 'jsonwebtoken';
|
||||
import {ErrorCode} from './utils';
|
||||
|
||||
import type {Config, Logger, Callback} from '@verdaccio/types';
|
||||
import type {$Response, NextFunction} from 'express';
|
||||
import type {$RequestExtend} from '../../types';
|
||||
import {aesDecrypt, aesEncrypt} from './crypto-utils';
|
||||
|
||||
const LoggerApi = require('./logger');
|
||||
/**
|
||||
|
@ -254,7 +254,9 @@ class Auth {
|
|||
this.logger.warn('basic authentication is deprecated, please use JWT instead');
|
||||
return credentials;
|
||||
} else if (scheme.toUpperCase() === 'BEARER') {
|
||||
credentials = this.aes_decrypt(new Buffer(parts[1], 'base64')).toString('utf8');
|
||||
const token = new Buffer(parts[1], 'base64');
|
||||
|
||||
credentials = aesDecrypt(token, this.secret).toString('utf8');
|
||||
return credentials;
|
||||
} else {
|
||||
return;
|
||||
|
@ -331,25 +333,8 @@ class Auth {
|
|||
/**
|
||||
* Encrypt a string.
|
||||
*/
|
||||
aes_encrypt(buf: Buffer): Buffer {
|
||||
const c = Crypto.createCipher('aes192', this.secret);
|
||||
const b1 = c.update(buf);
|
||||
const b2 = c.final();
|
||||
return Buffer.concat([b1, b2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dencrypt a string.
|
||||
*/
|
||||
aes_decrypt(buf: Buffer ) {
|
||||
try {
|
||||
const c = Crypto.createDecipher('aes192', this.secret);
|
||||
const b1 = c.update(buf);
|
||||
const b2 = c.final();
|
||||
return Buffer.concat([b1, b2]);
|
||||
} catch (_) {
|
||||
return new Buffer(0);
|
||||
}
|
||||
aesEncrypt(buf: Buffer): Buffer {
|
||||
return aesEncrypt(buf, this.secret);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import {generateRandomHexString} from './crypto-utils';
|
||||
|
||||
const assert = require('assert');
|
||||
const _ = require('lodash');
|
||||
const Error = require('http-errors');
|
||||
const Crypto = require('crypto');
|
||||
const minimatch = require('minimatch');
|
||||
|
||||
const Utils = require('./utils');
|
||||
|
@ -164,7 +165,7 @@ class Config {
|
|||
|
||||
// unique identifier of self server (or a cluster), used to avoid loops
|
||||
if (!self.server_id) {
|
||||
self.server_id = Crypto.pseudoRandomBytes(6).toString('hex');
|
||||
self.server_id = generateRandomHexString(6);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,7 +210,7 @@ class Config {
|
|||
}
|
||||
// it generates a secret key
|
||||
// FUTURE: this might be an external secret key, perhaps whitin config file?
|
||||
this.secret = Crypto.pseudoRandomBytes(32).toString('hex');
|
||||
this.secret = generateRandomHexString(32);
|
||||
return this.secret;
|
||||
}
|
||||
}
|
||||
|
|
43
src/lib/crypto-utils.js
Normal file
43
src/lib/crypto-utils.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
// @flow
|
||||
|
||||
import {createDecipher, createCipher, createHash, pseudoRandomBytes} from 'crypto';
|
||||
|
||||
export const defaultAlgorithm = 'aes192';
|
||||
|
||||
export function aesEncrypt(buf: Buffer, secret: string): Buffer {
|
||||
const c = createCipher(defaultAlgorithm, secret);
|
||||
const b1 = c.update(buf);
|
||||
const b2 = c.final();
|
||||
return Buffer.concat([b1, b2]);
|
||||
}
|
||||
|
||||
|
||||
export function aesDecrypt(buf: Buffer, secret: string) {
|
||||
try {
|
||||
const c = createDecipher(defaultAlgorithm, secret);
|
||||
const b1 = c.update(buf);
|
||||
const b2 = c.final();
|
||||
return Buffer.concat([b1, b2]);
|
||||
} catch (_) {
|
||||
return new Buffer(0);
|
||||
}
|
||||
}
|
||||
|
||||
export function createTarballHash() {
|
||||
return createHash('sha1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Express doesn't do etags with requests <= 1024b
|
||||
* we use md5 here, it works well on 1k+ bytes, but sucks with fewer data
|
||||
* could improve performance using crc32 after benchmarks.
|
||||
* @param {Object} data
|
||||
* @return {String}
|
||||
*/
|
||||
export function stringToMD5(data: Buffer | string) {
|
||||
return createHash('md5').update(data).digest('hex');
|
||||
}
|
||||
|
||||
export function generateRandomHexString(length: number = 8) {
|
||||
return pseudoRandomBytes(length).toString('hex');
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
/* eslint prefer-rest-params: 0 */
|
||||
|
||||
import Crypto from 'crypto';
|
||||
import assert from 'assert';
|
||||
import fs from 'fs';
|
||||
import Path from 'path';
|
||||
|
@ -13,27 +12,28 @@ import async from 'async';
|
|||
import {ErrorCode, isObject, getLatestVersion, tagVersion, validate_name, semverSort, DIST_TAGS} from './utils';
|
||||
import {
|
||||
generatePackageTemplate, normalizePackage, generateRevision, getLatestReadme, cleanUpReadme,
|
||||
fileExist, noSuchFile, DEFAULT_REVISION, pkgFileName,
|
||||
fileExist, noSuchFile, DEFAULT_REVISION, pkgFileName,
|
||||
} from './storage-utils';
|
||||
import {createTarballHash} from './crypto-utils';
|
||||
import {loadPlugin} from '../lib/plugin-loader';
|
||||
import LocalDatabase from '@verdaccio/local-storage';
|
||||
import {UploadTarball, ReadTarball} from '@verdaccio/streams';
|
||||
import type {
|
||||
Package,
|
||||
Config,
|
||||
MergeTags,
|
||||
Version,
|
||||
DistFile,
|
||||
Callback,
|
||||
Logger,
|
||||
Package,
|
||||
Config,
|
||||
MergeTags,
|
||||
Version,
|
||||
DistFile,
|
||||
Callback,
|
||||
Logger,
|
||||
} from '@verdaccio/types';
|
||||
import type {
|
||||
ILocalData,
|
||||
IPackageStorage,
|
||||
ILocalData,
|
||||
IPackageStorage,
|
||||
} from '@verdaccio/local-storage';
|
||||
import type {
|
||||
IUploadTarball,
|
||||
IReadTarball,
|
||||
IUploadTarball,
|
||||
IReadTarball,
|
||||
} from '@verdaccio/streams';
|
||||
import type {IStorage, StringValue} from '../../types';
|
||||
|
||||
|
@ -386,7 +386,7 @@ class LocalStorage implements IStorage {
|
|||
assert(validate_name(filename));
|
||||
|
||||
let length = 0;
|
||||
const shaOneHash = Crypto.createHash('sha1');
|
||||
const shaOneHash = createTarballHash();
|
||||
const uploadStream: IUploadTarball = new UploadTarball();
|
||||
const _transform = uploadStream._transform;
|
||||
const storage = this._getLocalStorage(name);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// @flow
|
||||
|
||||
import _ from 'lodash';
|
||||
import crypto from 'crypto';
|
||||
import {ErrorCode, isObject, normalizeDistTags, DIST_TAGS} from './utils';
|
||||
import Search from './search';
|
||||
import {generateRandomHexString} from '../lib/crypto-utils';
|
||||
|
||||
import type {Package, Version} from '@verdaccio/types';
|
||||
import type {IStorage} from '../../types';
|
||||
|
@ -60,7 +60,7 @@ function normalizePackage(pkg: Package) {
|
|||
function generateRevision(rev: string): string {
|
||||
const _rev = rev.split('-');
|
||||
|
||||
return ((+_rev[0] || 0) + 1) + '-' + crypto.pseudoRandomBytes(8).toString('hex');
|
||||
return ((+_rev[0] || 0) + 1) + '-' + generateRandomHexString();
|
||||
}
|
||||
|
||||
function getLatestReadme(pkg: Package): string {
|
||||
|
|
|
@ -1,13 +1,5 @@
|
|||
// @flow
|
||||
import crypto from 'crypto';
|
||||
|
||||
export function spliceURL(...args: Array<string>): string {
|
||||
return Array.from(args).reduce((lastResult, current) => lastResult + current).replace(/([^:])(\/)+(.)/g, `$1/$3`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get MD5 from string
|
||||
*/
|
||||
export function stringToMD5(string: string): string {
|
||||
return crypto.createHash('md5').update(string).digest('hex');
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// @flow
|
||||
import {stringToMD5} from './string';
|
||||
import {stringToMD5} from '../lib/crypto-utils';
|
||||
|
||||
|
||||
export const GRAVATAR_DEFAULT = 'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=mm';
|
||||
|
|
|
@ -23,7 +23,7 @@ export interface IAuth {
|
|||
logger: Logger;
|
||||
secret: string;
|
||||
plugins: Array<any>;
|
||||
aes_encrypt(buf: Buffer): Buffer;
|
||||
aesEncrypt(buf: Buffer): Buffer;
|
||||
apiJWTmiddleware(): $NextFunctionVer;
|
||||
webUIJWTmiddleware(): $NextFunctionVer;
|
||||
authenticate(user: string, password: string, cb: Callback): void;
|
||||
|
|
Loading…
Reference in a new issue