diff --git a/src/auth/scram.ts b/src/auth/scram.ts index 405032d..44f9aae 100644 --- a/src/auth/scram.ts +++ b/src/auth/scram.ts @@ -6,6 +6,7 @@ import { MongoDriverError } from "../error.ts"; import { b64, Binary, crypto as stdCrypto, Document, hex } from "../../deps.ts"; import { driverMetadata } from "../protocol/mod.ts"; import { pbkdf2 } from "./pbkdf2.ts"; +import { decodeBase64 } from "../utils/decodeBase64.ts"; type CryptoMethod = "sha1" | "sha256"; @@ -114,17 +115,6 @@ export async function executeScram( return continueScramConversation(cryptoMethod, result, authContext); } -function decodeBase64(b64: string): Uint8Array { - const b64Web = b64.replace(/-/g, "+").replace(/_/g, "/"); - const binString = atob(b64Web); - const size = binString.length; - const bytes = new Uint8Array(size); - for (let i = 0; i < size; i++) { - bytes[i] = binString.charCodeAt(i); - } - return bytes; -} - export async function continueScramConversation( cryptoMethod: CryptoMethod, response: Document, @@ -171,7 +161,7 @@ export async function continueScramConversation( const withoutProof = `c=biws,r=${rnonce}`; const saltedPassword = await HI( processedPassword, - b64.decode(salt), + decodeBase64(salt), iterations, cryptoMethod, ); diff --git a/src/utils/decodeBase64.ts b/src/utils/decodeBase64.ts new file mode 100644 index 0000000..16732d4 --- /dev/null +++ b/src/utils/decodeBase64.ts @@ -0,0 +1,24 @@ +export function decodeBase64(b64: string): Uint8Array { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + let base64 = b64.replace(/-/g, '+').replace(/_/g, '/'); + + while (base64.length % 4) { + base64 += '='; + } + + let bitString = ''; + for (let i = 0; i < base64.length; i++) { + const char = base64.charAt(i); + if (char !== '=') { + const charIndex = chars.indexOf(char); + bitString += charIndex.toString(2).padStart(6, '0'); + } + } + + const bytes = new Uint8Array(bitString.length / 8); + for (let i = 0; i < bytes.length; i++) { + bytes[i] = parseInt(bitString.substring(8 * i, 8 * (i + 1)), 2); + } + + return bytes; +}