mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
crypto/bcrypt: don't reimplement base64, just use a custom alphabet
Now that std.base64 supports everything bcrypt needs to encode its parameters, we don't need to include another implementation.
This commit is contained in:
parent
55c5da1b20
commit
22b71b1376
@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const base64 = std.base64;
|
||||
const crypto = std.crypto;
|
||||
const debug = std.debug;
|
||||
const fmt = std.fmt;
|
||||
@ -533,71 +534,10 @@ const crypt_format = struct {
|
||||
pub const prefix = "$2";
|
||||
|
||||
// bcrypt has its own variant of base64, with its own alphabet and no padding
|
||||
const Codec = struct {
|
||||
const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
fn encode(b64: []u8, bin: []const u8) void {
|
||||
var i: usize = 0;
|
||||
var j: usize = 0;
|
||||
while (i < bin.len) {
|
||||
var c1 = bin[i];
|
||||
i += 1;
|
||||
b64[j] = alphabet[c1 >> 2];
|
||||
j += 1;
|
||||
c1 = (c1 & 3) << 4;
|
||||
if (i >= bin.len) {
|
||||
b64[j] = alphabet[c1];
|
||||
j += 1;
|
||||
break;
|
||||
}
|
||||
var c2 = bin[i];
|
||||
i += 1;
|
||||
c1 |= (c2 >> 4) & 0x0f;
|
||||
b64[j] = alphabet[c1];
|
||||
j += 1;
|
||||
c1 = (c2 & 0x0f) << 2;
|
||||
if (i >= bin.len) {
|
||||
b64[j] = alphabet[c1];
|
||||
j += 1;
|
||||
break;
|
||||
}
|
||||
c2 = bin[i];
|
||||
i += 1;
|
||||
c1 |= (c2 >> 6) & 3;
|
||||
b64[j] = alphabet[c1];
|
||||
b64[j + 1] = alphabet[c2 & 0x3f];
|
||||
j += 2;
|
||||
}
|
||||
debug.assert(j == b64.len);
|
||||
}
|
||||
|
||||
fn decode(bin: []u8, b64: []const u8) EncodingError!void {
|
||||
var i: usize = 0;
|
||||
var j: usize = 0;
|
||||
while (j < bin.len) {
|
||||
const c1 = @intCast(u8, mem.indexOfScalar(u8, alphabet, b64[i]) orelse
|
||||
return EncodingError.InvalidEncoding);
|
||||
const c2 = @intCast(u8, mem.indexOfScalar(u8, alphabet, b64[i + 1]) orelse
|
||||
return EncodingError.InvalidEncoding);
|
||||
bin[j] = (c1 << 2) | ((c2 & 0x30) >> 4);
|
||||
j += 1;
|
||||
if (j >= bin.len) {
|
||||
break;
|
||||
}
|
||||
const c3 = @intCast(u8, mem.indexOfScalar(u8, alphabet, b64[i + 2]) orelse
|
||||
return EncodingError.InvalidEncoding);
|
||||
bin[j] = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
|
||||
j += 1;
|
||||
if (j >= bin.len) {
|
||||
break;
|
||||
}
|
||||
const c4 = @intCast(u8, mem.indexOfScalar(u8, alphabet, b64[i + 3]) orelse
|
||||
return EncodingError.InvalidEncoding);
|
||||
bin[j] = ((c3 & 0x03) << 6) | c4;
|
||||
j += 1;
|
||||
i += 4;
|
||||
}
|
||||
}
|
||||
const bcrypt_alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".*;
|
||||
const Codec = struct { Encoder: base64.Base64Encoder, Decoder: base64.Base64Decoder }{
|
||||
.Encoder = base64.Base64Encoder.init(bcrypt_alphabet, null),
|
||||
.Decoder = base64.Base64Decoder.init(bcrypt_alphabet, null),
|
||||
};
|
||||
|
||||
fn strHashInternal(
|
||||
@ -608,10 +548,10 @@ const crypt_format = struct {
|
||||
var dk = bcrypt(password, salt, params);
|
||||
|
||||
var salt_str: [salt_str_length]u8 = undefined;
|
||||
Codec.encode(salt_str[0..], salt[0..]);
|
||||
_ = Codec.Encoder.encode(salt_str[0..], salt[0..]);
|
||||
|
||||
var ct_str: [ct_str_length]u8 = undefined;
|
||||
Codec.encode(ct_str[0..], dk[0..]);
|
||||
_ = Codec.Encoder.encode(ct_str[0..], dk[0..]);
|
||||
|
||||
var s_buf: [hash_length]u8 = undefined;
|
||||
const s = fmt.bufPrint(
|
||||
@ -709,7 +649,7 @@ const CryptFormatHasher = struct {
|
||||
|
||||
const salt_str = str[7..][0..salt_str_length];
|
||||
var salt: [salt_length]u8 = undefined;
|
||||
try crypt_format.Codec.decode(salt[0..], salt_str[0..]);
|
||||
crypt_format.Codec.Decoder.decode(salt[0..], salt_str[0..]) catch return HasherError.InvalidEncoding;
|
||||
|
||||
const wanted_s = crypt_format.strHashInternal(password, salt, .{ .rounds_log = rounds_log });
|
||||
if (!mem.eql(u8, wanted_s[0..], str[0..])) return HasherError.PasswordVerificationFailed;
|
||||
@ -764,9 +704,9 @@ test "bcrypt codec" {
|
||||
var salt: [salt_length]u8 = undefined;
|
||||
crypto.random.bytes(&salt);
|
||||
var salt_str: [salt_str_length]u8 = undefined;
|
||||
crypt_format.Codec.encode(salt_str[0..], salt[0..]);
|
||||
_ = crypt_format.Codec.Encoder.encode(salt_str[0..], salt[0..]);
|
||||
var salt2: [salt_length]u8 = undefined;
|
||||
try crypt_format.Codec.decode(salt2[0..], salt_str[0..]);
|
||||
try crypt_format.Codec.Decoder.decode(salt2[0..], salt_str[0..]);
|
||||
try testing.expectEqualSlices(u8, salt[0..], salt2[0..]);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user