Skip to content

Commit

Permalink
chore(deps): drop std/hash (#301)
Browse files Browse the repository at this point in the history
* chore(deps): drop std/hash
* bump(deps) update std
  • Loading branch information
erfanium authored Nov 30, 2021
1 parent a67f6bc commit 530ef7d
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 39 deletions.
17 changes: 8 additions & 9 deletions deps.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
export * as Bson from "./bson/bson.ts";
export { createHash } from "https://deno.land/std@0.115.1/hash/mod.ts";
export { HmacSha1 } from "https://deno.land/std@0.115.1/hash/sha1.ts";
export { HmacSha256 } from "https://deno.land/std@0.115.1/hash/sha256.ts";
export { BufReader } from "https://deno.land/std@0.115.1/io/mod.ts";
export { writeAll } from "https://deno.land/std@0.115.1/streams/conversion.ts";
export { deferred } from "https://deno.land/std@0.115.1/async/deferred.ts";
export type { Deferred } from "https://deno.land/std@0.115.1/async/deferred.ts";
export * as b64 from "https://deno.land/std@0.115.1/encoding/base64.ts";
export { crypto } from "https://deno.land/std@0.116.0/crypto/mod.ts";
export { BufReader } from "https://deno.land/std@0.116.0/io/mod.ts";
export { writeAll } from "https://deno.land/std@0.116.0/streams/conversion.ts";
export { deferred } from "https://deno.land/std@0.116.0/async/deferred.ts";
export type { Deferred } from "https://deno.land/std@0.116.0/async/deferred.ts";
export * as b64 from "https://deno.land/std@0.116.0/encoding/base64.ts";
export * as hex from "https://deno.land/std@0.116.0/encoding/hex.ts";
export {
assert,
assertEquals,
} from "https://deno.land/std@0.115.1/testing/asserts.ts";
} from "https://deno.land/std@0.116.0/testing/asserts.ts";
80 changes: 54 additions & 26 deletions src/auth/scram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { saslprep } from "../utils/saslprep/mod.ts";
import { AuthContext, AuthPlugin } from "./base.ts";
import { HandshakeDocument } from "../protocol/handshake.ts";
import { MongoDriverError } from "../error.ts";
import { b64, Bson, createHash, HmacSha1, HmacSha256 } from "../../deps.ts";
import { b64, Bson, crypto as stdCrypto, hex } from "../../deps.ts";
import { driverMetadata } from "../protocol/mod.ts";
import { pbkdf2 } from "./pbkdf2.ts";

Expand Down Expand Up @@ -137,7 +137,7 @@ export async function continueScramConversation(
if (cryptoMethod === "sha256") {
processedPassword = saslprep(password);
} else {
processedPassword = passwordDigest(username, password);
processedPassword = await passwordDigest(username, password);
}

const payload = fixPayload(dec.decode(response.payload.buffer));
Expand Down Expand Up @@ -165,21 +165,20 @@ export async function continueScramConversation(
cryptoMethod,
);

const clientKey = HMAC(cryptoMethod, saltedPassword, "Client Key");

const serverKey = HMAC(cryptoMethod, saltedPassword, "Server Key");
const storedKey = H(cryptoMethod, clientKey);
const clientKey = await HMAC(cryptoMethod, saltedPassword, "Client Key");
const serverKey = await HMAC(cryptoMethod, saltedPassword, "Server Key");
const storedKey = await H(cryptoMethod, clientKey);
const authMessage = [
dec.decode(clientFirstMessageBare(username, nonce)),
payload,
withoutProof,
].join(",");

const clientSignature = HMAC(cryptoMethod, storedKey, authMessage);
const clientSignature = await HMAC(cryptoMethod, storedKey, authMessage);
const clientProof = `p=${xor(clientKey, clientSignature)}`;
const clientFinal = [withoutProof, clientProof].join(",");

const serverSignature = HMAC(cryptoMethod, serverKey, authMessage);
const serverSignature = await HMAC(cryptoMethod, serverKey, authMessage);

const saslContinueCmd = {
saslContinue: 1,
Expand All @@ -192,7 +191,12 @@ export async function continueScramConversation(
const parsedResponse = parsePayload(
fixPayload2(dec.decode(result.payload.buffer)),
);
if (!compareDigest(b64.decode(parsedResponse.v), serverSignature)) {
if (
!compareDigest(
b64.decode(parsedResponse.v),
new Uint8Array(serverSignature),
)
) {
// throw new MongoDriverError("Server returned an invalid signature");
}
if (result.done) {
Expand Down Expand Up @@ -236,7 +240,10 @@ export function parsePayload(payload: string) {
return dict;
}

export function passwordDigest(username: string, password: string) {
export async function passwordDigest(
username: string,
password: string,
): Promise<string> {
if (typeof username !== "string") {
throw new MongoDriverError("username must be a string");
}
Expand All @@ -249,13 +256,18 @@ export function passwordDigest(username: string, password: string) {
throw new MongoDriverError("password cannot be empty");
}

const md5 = createHash("md5");
md5.update(`${username}:mongo:${password}`);
return md5.toString(); //hex
const result = await stdCrypto.subtle.digest(
"MD5",
enc.encode(`${username}:mongo:${password}`),
);
return dec.decode(hex.encode(new Uint8Array(result)));
}

// XOR two buffers
export function xor(a: Uint8Array, b: Uint8Array) {
export function xor(_a: ArrayBuffer, _b: ArrayBuffer) {
const a = new Uint8Array(_a);
const b = new Uint8Array(_b);

const length = Math.max(a.length, b.length);
const res = new Uint8Array(length);

Expand All @@ -266,20 +278,36 @@ export function xor(a: Uint8Array, b: Uint8Array) {
return b64.encode(res);
}

export function H(method: CryptoMethod, text: Uint8Array) {
return new Uint8Array(createHash(method).update(text).digest());
export function H(method: CryptoMethod, text: BufferSource) {
return crypto.subtle.digest(
method === "sha256" ? "SHA-256" : "SHA-1",
text,
);
}

export function HMAC(
export async function HMAC(
method: CryptoMethod,
key: ArrayBuffer,
text: Uint8Array | string,
secret: ArrayBuffer,
text: string,
) {
if (method === "sha256") {
return new Uint8Array(new HmacSha256(key).update(text).digest());
} else {
return new Uint8Array(new HmacSha1(key).update(text).digest());
}
const key = await crypto.subtle.importKey(
"raw",
secret,
{
name: "HMAC",
hash: method === "sha256" ? "SHA-256" : "SHA-1",
},
false,
["sign", "verify"],
);

const signature = await crypto.subtle.sign(
"HMAC",
key,
enc.encode(text),
);

return signature;
}

interface HICache {
Expand All @@ -303,7 +331,7 @@ export async function HI(
salt: Uint8Array,
iterations: number,
cryptoMethod: CryptoMethod,
) {
): Promise<ArrayBuffer> {
// omit the work if already generated
const key = [data, b64.encode(salt), iterations].join(
"_",
Expand All @@ -328,7 +356,7 @@ export async function HI(

_hiCache[key] = saltedData;
_hiCacheCount += 1;
return new Uint8Array(saltedData);
return saltedData;
}

export function compareDigest(lhs: Uint8Array, rhs: Uint8Array) {
Expand Down
6 changes: 3 additions & 3 deletions tests/cases/01_auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ export default function authTests() {
for (const { username, password, digest } of passwordValids) {
Deno.test({
name: `passwordDigest:${username}:${password}`,
fn() {
const digestRes: string = passwordDigest(username, password);
async fn() {
const digestRes: string = await passwordDigest(username, password);
assertEquals(digestRes, digest);
},
});
Expand Down Expand Up @@ -95,7 +95,7 @@ export default function authTests() {
"sha1",
);
assertEquals(
saltedPassword,
new Uint8Array(saltedPassword),
Uint8Array.from([
72,
84,
Expand Down
2 changes: 1 addition & 1 deletion tests/test.deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ export {
assertEquals,
assertThrows,
assertThrowsAsync,
} from "https://deno.land/std@0.115.1/testing/asserts.ts";
} from "https://deno.land/std@0.116.0/testing/asserts.ts";
export * as semver from "https://deno.land/x/semver@v1.4.0/mod.ts";

0 comments on commit 530ef7d

Please sign in to comment.