authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2022-10-25 20:34:24+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-25 21:52:03-07:00
log22b71b1376eaa75aa141022404d6ddf40495c886
tree23bc42609018817fca9d688d6288f1b2c4e77e59
parent55c5da1b205dc5eddd2749381caacf28bea6f90e

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.

1 files changed, 10 insertions(+), 70 deletions(-)

lib/std/crypto/bcrypt.zig+10-70
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const base64 = std.base64;
2const crypto = std.crypto;3const crypto = std.crypto;
3const debug = std.debug;4const debug = std.debug;
4const fmt = std.fmt;5const fmt = std.fmt;
...@@ -533,71 +534,10 @@ const crypt_format = struct {...@@ -533,71 +534,10 @@ const crypt_format = struct {
533 pub const prefix = "$2";534 pub const prefix = "$2";
534535
535 // bcrypt has its own variant of base64, with its own alphabet and no padding536 // bcrypt has its own variant of base64, with its own alphabet and no padding
536 const Codec = struct {537 const bcrypt_alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".*;
537 const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";538 const Codec = struct { Encoder: base64.Base64Encoder, Decoder: base64.Base64Decoder }{
538539 .Encoder = base64.Base64Encoder.init(bcrypt_alphabet, null),
539 fn encode(b64: []u8, bin: []const u8) void {540 .Decoder = base64.Base64Decoder.init(bcrypt_alphabet, null),
540 var i: usize = 0;
541 var j: usize = 0;
542 while (i < bin.len) {
543 var c1 = bin[i];
544 i += 1;
545 b64[j] = alphabet[c1 >> 2];
546 j += 1;
547 c1 = (c1 & 3) << 4;
548 if (i >= bin.len) {
549 b64[j] = alphabet[c1];
550 j += 1;
551 break;
552 }
553 var c2 = bin[i];
554 i += 1;
555 c1 |= (c2 >> 4) & 0x0f;
556 b64[j] = alphabet[c1];
557 j += 1;
558 c1 = (c2 & 0x0f) << 2;
559 if (i >= bin.len) {
560 b64[j] = alphabet[c1];
561 j += 1;
562 break;
563 }
564 c2 = bin[i];
565 i += 1;
566 c1 |= (c2 >> 6) & 3;
567 b64[j] = alphabet[c1];
568 b64[j + 1] = alphabet[c2 & 0x3f];
569 j += 2;
570 }
571 debug.assert(j == b64.len);
572 }
573
574 fn decode(bin: []u8, b64: []const u8) EncodingError!void {
575 var i: usize = 0;
576 var j: usize = 0;
577 while (j < bin.len) {
578 const c1 = @intCast(u8, mem.indexOfScalar(u8, alphabet, b64[i]) orelse
579 return EncodingError.InvalidEncoding);
580 const c2 = @intCast(u8, mem.indexOfScalar(u8, alphabet, b64[i + 1]) orelse
581 return EncodingError.InvalidEncoding);
582 bin[j] = (c1 << 2) | ((c2 & 0x30) >> 4);
583 j += 1;
584 if (j >= bin.len) {
585 break;
586 }
587 const c3 = @intCast(u8, mem.indexOfScalar(u8, alphabet, b64[i + 2]) orelse
588 return EncodingError.InvalidEncoding);
589 bin[j] = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
590 j += 1;
591 if (j >= bin.len) {
592 break;
593 }
594 const c4 = @intCast(u8, mem.indexOfScalar(u8, alphabet, b64[i + 3]) orelse
595 return EncodingError.InvalidEncoding);
596 bin[j] = ((c3 & 0x03) << 6) | c4;
597 j += 1;
598 i += 4;
599 }
600 }
601 };541 };
602542
603 fn strHashInternal(543 fn strHashInternal(
...@@ -608,10 +548,10 @@ const crypt_format = struct {...@@ -608,10 +548,10 @@ const crypt_format = struct {
608 var dk = bcrypt(password, salt, params);548 var dk = bcrypt(password, salt, params);
609549
610 var salt_str: [salt_str_length]u8 = undefined;550 var salt_str: [salt_str_length]u8 = undefined;
611 Codec.encode(salt_str[0..], salt[0..]);551 _ = Codec.Encoder.encode(salt_str[0..], salt[0..]);
612552
613 var ct_str: [ct_str_length]u8 = undefined;553 var ct_str: [ct_str_length]u8 = undefined;
614 Codec.encode(ct_str[0..], dk[0..]);554 _ = Codec.Encoder.encode(ct_str[0..], dk[0..]);
615555
616 var s_buf: [hash_length]u8 = undefined;556 var s_buf: [hash_length]u8 = undefined;
617 const s = fmt.bufPrint(557 const s = fmt.bufPrint(
...@@ -709,7 +649,7 @@ const CryptFormatHasher = struct {...@@ -709,7 +649,7 @@ const CryptFormatHasher = struct {
709649
710 const salt_str = str[7..][0..salt_str_length];650 const salt_str = str[7..][0..salt_str_length];
711 var salt: [salt_length]u8 = undefined;651 var salt: [salt_length]u8 = undefined;
712 try crypt_format.Codec.decode(salt[0..], salt_str[0..]);652 crypt_format.Codec.Decoder.decode(salt[0..], salt_str[0..]) catch return HasherError.InvalidEncoding;
713653
714 const wanted_s = crypt_format.strHashInternal(password, salt, .{ .rounds_log = rounds_log });654 const wanted_s = crypt_format.strHashInternal(password, salt, .{ .rounds_log = rounds_log });
715 if (!mem.eql(u8, wanted_s[0..], str[0..])) return HasherError.PasswordVerificationFailed;655 if (!mem.eql(u8, wanted_s[0..], str[0..])) return HasherError.PasswordVerificationFailed;
...@@ -764,9 +704,9 @@ test "bcrypt codec" {...@@ -764,9 +704,9 @@ test "bcrypt codec" {
764 var salt: [salt_length]u8 = undefined;704 var salt: [salt_length]u8 = undefined;
765 crypto.random.bytes(&salt);705 crypto.random.bytes(&salt);
766 var salt_str: [salt_str_length]u8 = undefined;706 var salt_str: [salt_str_length]u8 = undefined;
767 crypt_format.Codec.encode(salt_str[0..], salt[0..]);707 _ = crypt_format.Codec.Encoder.encode(salt_str[0..], salt[0..]);
768 var salt2: [salt_length]u8 = undefined;708 var salt2: [salt_length]u8 = undefined;
769 try crypt_format.Codec.decode(salt2[0..], salt_str[0..]);709 try crypt_format.Codec.Decoder.decode(salt2[0..], salt_str[0..]);
770 try testing.expectEqualSlices(u8, salt[0..], salt2[0..]);710 try testing.expectEqualSlices(u8, salt[0..], salt2[0..]);
771}711}
772712