| author | |
| committer | |
| log | b98d7747fa7fb86d5f3f9bdbd00901e16fc58fca |
| tree | 4c054a9bfb1c0d53f5d57a297974e5e0255dc026 |
| parent | f69305f865c346ffb2a00403efd0768f8bbdd20b |
This ensures that errors are used consistently across all operations.18 files changed, 126 insertions(+), 87 deletions(-)
lib/std/crypto.zig+5-1| ... | @@ -144,6 +144,8 @@ pub const random = &@import("crypto/tlcsprng.zig").interface; | ... | @@ -144,6 +144,8 @@ pub const random = &@import("crypto/tlcsprng.zig").interface; |
| 144 | 144 | ||
| 145 | const std = @import("std.zig"); | 145 | const std = @import("std.zig"); |
| 146 | 146 | ||
| 147 | pub const Error = @import("crypto/error.zig").Error; | ||
| 148 | |||
| 147 | test "crypto" { | 149 | test "crypto" { |
| 148 | const please_windows_dont_oom = std.Target.current.os.tag == .windows; | 150 | const please_windows_dont_oom = std.Target.current.os.tag == .windows; |
| 149 | if (please_windows_dont_oom) return error.SkipZigTest; | 151 | if (please_windows_dont_oom) return error.SkipZigTest; |
| ... | @@ -151,7 +153,9 @@ test "crypto" { | ... | @@ -151,7 +153,9 @@ test "crypto" { |
| 151 | inline for (std.meta.declarations(@This())) |decl| { | 153 | inline for (std.meta.declarations(@This())) |decl| { |
| 152 | switch (decl.data) { | 154 | switch (decl.data) { |
| 153 | .Type => |t| { | 155 | .Type => |t| { |
| 154 | std.testing.refAllDecls(t); | 156 | if (@typeInfo(t) != .ErrorSet) { |
| 157 | std.testing.refAllDecls(t); | ||
| 158 | } | ||
| 155 | }, | 159 | }, |
| 156 | .Var => |v| { | 160 | .Var => |v| { |
| 157 | _ = v; | 161 | _ = v; |
lib/std/crypto/25519/curve25519.zig+7-6| ... | @@ -4,6 +4,7 @@ | ... | @@ -4,6 +4,7 @@ |
| 4 | // The MIT license requires this copyright notice to be included in all copies | 4 | // The MIT license requires this copyright notice to be included in all copies |
| 5 | // and substantial portions of the software. | 5 | // and substantial portions of the software. |
| 6 | const std = @import("std"); | 6 | const std = @import("std"); |
| 7 | const Error = std.crypto.Error; | ||
| 7 | 8 | ||
| 8 | /// Group operations over Curve25519. | 9 | /// Group operations over Curve25519. |
| 9 | pub const Curve25519 = struct { | 10 | pub const Curve25519 = struct { |
| ... | @@ -28,12 +29,12 @@ pub const Curve25519 = struct { | ... | @@ -28,12 +29,12 @@ pub const Curve25519 = struct { |
| 28 | pub const basePoint = Curve25519{ .x = Fe.curve25519BasePoint }; | 29 | pub const basePoint = Curve25519{ .x = Fe.curve25519BasePoint }; |
| 29 | 30 | ||
| 30 | /// Check that the encoding of a Curve25519 point is canonical. | 31 | /// Check that the encoding of a Curve25519 point is canonical. |
| 31 | pub fn rejectNonCanonical(s: [32]u8) !void { | 32 | pub fn rejectNonCanonical(s: [32]u8) Error!void { |
| 32 | return Fe.rejectNonCanonical(s, false); | 33 | return Fe.rejectNonCanonical(s, false); |
| 33 | } | 34 | } |
| 34 | 35 | ||
| 35 | /// Reject the neutral element. | 36 | /// Reject the neutral element. |
| 36 | pub fn rejectIdentity(p: Curve25519) !void { | 37 | pub fn rejectIdentity(p: Curve25519) Error!void { |
| 37 | if (p.x.isZero()) { | 38 | if (p.x.isZero()) { |
| 38 | return error.IdentityElement; | 39 | return error.IdentityElement; |
| 39 | } | 40 | } |
| ... | @@ -44,7 +45,7 @@ pub const Curve25519 = struct { | ... | @@ -44,7 +45,7 @@ pub const Curve25519 = struct { |
| 44 | return p.dbl().dbl().dbl(); | 45 | return p.dbl().dbl().dbl(); |
| 45 | } | 46 | } |
| 46 | 47 | ||
| 47 | fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) !Curve25519 { | 48 | fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) Error!Curve25519 { |
| 48 | var x1 = p.x; | 49 | var x1 = p.x; |
| 49 | var x2 = Fe.one; | 50 | var x2 = Fe.one; |
| 50 | var z2 = Fe.zero; | 51 | var z2 = Fe.zero; |
| ... | @@ -85,7 +86,7 @@ pub const Curve25519 = struct { | ... | @@ -85,7 +86,7 @@ pub const Curve25519 = struct { |
| 85 | /// way to use Curve25519 for a DH operation. | 86 | /// way to use Curve25519 for a DH operation. |
| 86 | /// Return error.IdentityElement if the resulting point is | 87 | /// Return error.IdentityElement if the resulting point is |
| 87 | /// the identity element. | 88 | /// the identity element. |
| 88 | pub fn clampedMul(p: Curve25519, s: [32]u8) !Curve25519 { | 89 | pub fn clampedMul(p: Curve25519, s: [32]u8) Error!Curve25519 { |
| 89 | var t: [32]u8 = s; | 90 | var t: [32]u8 = s; |
| 90 | scalar.clamp(&t); | 91 | scalar.clamp(&t); |
| 91 | return try ladder(p, t, 255); | 92 | return try ladder(p, t, 255); |
| ... | @@ -95,14 +96,14 @@ pub const Curve25519 = struct { | ... | @@ -95,14 +96,14 @@ pub const Curve25519 = struct { |
| 95 | /// Return error.IdentityElement if the resulting point is | 96 | /// Return error.IdentityElement if the resulting point is |
| 96 | /// the identity element or error.WeakPublicKey if the public | 97 | /// the identity element or error.WeakPublicKey if the public |
| 97 | /// key is a low-order point. | 98 | /// key is a low-order point. |
| 98 | pub fn mul(p: Curve25519, s: [32]u8) !Curve25519 { | 99 | pub fn mul(p: Curve25519, s: [32]u8) Error!Curve25519 { |
| 99 | const cofactor = [_]u8{8} ++ [_]u8{0} ** 31; | 100 | const cofactor = [_]u8{8} ++ [_]u8{0} ** 31; |
| 100 | _ = ladder(p, cofactor, 4) catch |_| return error.WeakPublicKey; | 101 | _ = ladder(p, cofactor, 4) catch |_| return error.WeakPublicKey; |
| 101 | return try ladder(p, s, 256); | 102 | return try ladder(p, s, 256); |
| 102 | } | 103 | } |
| 103 | 104 | ||
| 104 | /// Compute the Curve25519 equivalent to an Edwards25519 point. | 105 | /// Compute the Curve25519 equivalent to an Edwards25519 point. |
| 105 | pub fn fromEdwards25519(p: std.crypto.ecc.Edwards25519) !Curve25519 { | 106 | pub fn fromEdwards25519(p: std.crypto.ecc.Edwards25519) Error!Curve25519 { |
| 106 | try p.clearCofactor().rejectIdentity(); | 107 | try p.clearCofactor().rejectIdentity(); |
| 107 | const one = std.crypto.ecc.Edwards25519.Fe.one; | 108 | const one = std.crypto.ecc.Edwards25519.Fe.one; |
| 108 | const x = one.add(p.y).mul(one.sub(p.y).invert()); // xMont=(1+yEd)/(1-yEd) | 109 | const x = one.add(p.y).mul(one.sub(p.y).invert()); // xMont=(1+yEd)/(1-yEd) |
lib/std/crypto/25519/ed25519.zig+12-11| ... | @@ -8,7 +8,8 @@ const crypto = std.crypto; | ... | @@ -8,7 +8,8 @@ const crypto = std.crypto; |
| 8 | const debug = std.debug; | 8 | const debug = std.debug; |
| 9 | const fmt = std.fmt; | 9 | const fmt = std.fmt; |
| 10 | const mem = std.mem; | 10 | const mem = std.mem; |
| 11 | const Sha512 = std.crypto.hash.sha2.Sha512; | 11 | const Sha512 = crypto.hash.sha2.Sha512; |
| 12 | const Error = crypto.Error; | ||
| 12 | 13 | ||
| 13 | /// Ed25519 (EdDSA) signatures. | 14 | /// Ed25519 (EdDSA) signatures. |
| 14 | pub const Ed25519 = struct { | 15 | pub const Ed25519 = struct { |
| ... | @@ -40,7 +41,7 @@ pub const Ed25519 = struct { | ... | @@ -40,7 +41,7 @@ pub const Ed25519 = struct { |
| 40 | /// | 41 | /// |
| 41 | /// For this reason, an EdDSA secret key is commonly called a seed, | 42 | /// For this reason, an EdDSA secret key is commonly called a seed, |
| 42 | /// from which the actual secret is derived. | 43 | /// from which the actual secret is derived. |
| 43 | pub fn create(seed: ?[seed_length]u8) !KeyPair { | 44 | pub fn create(seed: ?[seed_length]u8) Error!KeyPair { |
| 44 | const ss = seed orelse ss: { | 45 | const ss = seed orelse ss: { |
| 45 | var random_seed: [seed_length]u8 = undefined; | 46 | var random_seed: [seed_length]u8 = undefined; |
| 46 | crypto.random.bytes(&random_seed); | 47 | crypto.random.bytes(&random_seed); |
| ... | @@ -71,7 +72,7 @@ pub const Ed25519 = struct { | ... | @@ -71,7 +72,7 @@ pub const Ed25519 = struct { |
| 71 | /// Sign a message using a key pair, and optional random noise. | 72 | /// Sign a message using a key pair, and optional random noise. |
| 72 | /// Having noise creates non-standard, non-deterministic signatures, | 73 | /// Having noise creates non-standard, non-deterministic signatures, |
| 73 | /// but has been proven to increase resilience against fault attacks. | 74 | /// but has been proven to increase resilience against fault attacks. |
| 74 | pub fn sign(msg: []const u8, key_pair: KeyPair, noise: ?[noise_length]u8) ![signature_length]u8 { | 75 | pub fn sign(msg: []const u8, key_pair: KeyPair, noise: ?[noise_length]u8) Error![signature_length]u8 { |
| 75 | const seed = key_pair.secret_key[0..seed_length]; | 76 | const seed = key_pair.secret_key[0..seed_length]; |
| 76 | const public_key = key_pair.secret_key[seed_length..]; | 77 | const public_key = key_pair.secret_key[seed_length..]; |
| 77 | if (!mem.eql(u8, public_key, &key_pair.public_key)) { | 78 | if (!mem.eql(u8, public_key, &key_pair.public_key)) { |
| ... | @@ -111,8 +112,8 @@ pub const Ed25519 = struct { | ... | @@ -111,8 +112,8 @@ pub const Ed25519 = struct { |
| 111 | } | 112 | } |
| 112 | 113 | ||
| 113 | /// Verify an Ed25519 signature given a message and a public key. | 114 | /// Verify an Ed25519 signature given a message and a public key. |
| 114 | /// Returns error.InvalidSignature is the signature verification failed. | 115 | /// Returns error.SignatureVerificationFailed is the signature verification failed. |
| 115 | pub fn verify(sig: [signature_length]u8, msg: []const u8, public_key: [public_length]u8) !void { | 116 | pub fn verify(sig: [signature_length]u8, msg: []const u8, public_key: [public_length]u8) Error!void { |
| 116 | const r = sig[0..32]; | 117 | const r = sig[0..32]; |
| 117 | const s = sig[32..64]; | 118 | const s = sig[32..64]; |
| 118 | try Curve.scalar.rejectNonCanonical(s.*); | 119 | try Curve.scalar.rejectNonCanonical(s.*); |
| ... | @@ -133,7 +134,7 @@ pub const Ed25519 = struct { | ... | @@ -133,7 +134,7 @@ pub const Ed25519 = struct { |
| 133 | const ah = try a.neg().mulPublic(hram); | 134 | const ah = try a.neg().mulPublic(hram); |
| 134 | const sb_ah = (try Curve.basePoint.mulPublic(s.*)).add(ah); | 135 | const sb_ah = (try Curve.basePoint.mulPublic(s.*)).add(ah); |
| 135 | if (expected_r.sub(sb_ah).clearCofactor().rejectIdentity()) |_| { | 136 | if (expected_r.sub(sb_ah).clearCofactor().rejectIdentity()) |_| { |
| 136 | return error.InvalidSignature; | 137 | return error.SignatureVerificationFailed; |
| 137 | } else |_| {} | 138 | } else |_| {} |
| 138 | } | 139 | } |
| 139 | 140 | ||
| ... | @@ -145,7 +146,7 @@ pub const Ed25519 = struct { | ... | @@ -145,7 +146,7 @@ pub const Ed25519 = struct { |
| 145 | }; | 146 | }; |
| 146 | 147 | ||
| 147 | /// Verify several signatures in a single operation, much faster than verifying signatures one-by-one | 148 | /// Verify several signatures in a single operation, much faster than verifying signatures one-by-one |
| 148 | pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) !void { | 149 | pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) Error!void { |
| 149 | var r_batch: [count][32]u8 = undefined; | 150 | var r_batch: [count][32]u8 = undefined; |
| 150 | var s_batch: [count][32]u8 = undefined; | 151 | var s_batch: [count][32]u8 = undefined; |
| 151 | var a_batch: [count]Curve = undefined; | 152 | var a_batch: [count]Curve = undefined; |
| ... | @@ -200,7 +201,7 @@ pub const Ed25519 = struct { | ... | @@ -200,7 +201,7 @@ pub const Ed25519 = struct { |
| 200 | 201 | ||
| 201 | const zsb = try Curve.basePoint.mulPublic(zs_sum); | 202 | const zsb = try Curve.basePoint.mulPublic(zs_sum); |
| 202 | if (zr.add(zah).sub(zsb).rejectIdentity()) |_| { | 203 | if (zr.add(zah).sub(zsb).rejectIdentity()) |_| { |
| 203 | return error.InvalidSignature; | 204 | return error.SignatureVerificationFailed; |
| 204 | } else |_| {} | 205 | } else |_| {} |
| 205 | } | 206 | } |
| 206 | }; | 207 | }; |
| ... | @@ -223,7 +224,7 @@ test "ed25519 signature" { | ... | @@ -223,7 +224,7 @@ test "ed25519 signature" { |
| 223 | var buf: [128]u8 = undefined; | 224 | var buf: [128]u8 = undefined; |
| 224 | std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&sig)}), "10A442B4A80CC4225B154F43BEF28D2472CA80221951262EB8E0DF9091575E2687CC486E77263C3418C757522D54F84B0359236ABBBD4ACD20DC297FDCA66808"); | 225 | std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&sig)}), "10A442B4A80CC4225B154F43BEF28D2472CA80221951262EB8E0DF9091575E2687CC486E77263C3418C757522D54F84B0359236ABBBD4ACD20DC297FDCA66808"); |
| 225 | try Ed25519.verify(sig, "test", key_pair.public_key); | 226 | try Ed25519.verify(sig, "test", key_pair.public_key); |
| 226 | std.testing.expectError(error.InvalidSignature, Ed25519.verify(sig, "TEST", key_pair.public_key)); | 227 | std.testing.expectError(error.SignatureVerificationFailed, Ed25519.verify(sig, "TEST", key_pair.public_key)); |
| 227 | } | 228 | } |
| 228 | 229 | ||
| 229 | test "ed25519 batch verification" { | 230 | test "ed25519 batch verification" { |
| ... | @@ -251,7 +252,7 @@ test "ed25519 batch verification" { | ... | @@ -251,7 +252,7 @@ test "ed25519 batch verification" { |
| 251 | try Ed25519.verifyBatch(2, signature_batch); | 252 | try Ed25519.verifyBatch(2, signature_batch); |
| 252 | 253 | ||
| 253 | signature_batch[1].sig = sig1; | 254 | signature_batch[1].sig = sig1; |
| 254 | std.testing.expectError(error.InvalidSignature, Ed25519.verifyBatch(signature_batch.len, signature_batch)); | 255 | std.testing.expectError(error.SignatureVerificationFailed, Ed25519.verifyBatch(signature_batch.len, signature_batch)); |
| 255 | } | 256 | } |
| 256 | } | 257 | } |
| 257 | 258 | ||
| ... | @@ -316,7 +317,7 @@ test "ed25519 test vectors" { | ... | @@ -316,7 +317,7 @@ test "ed25519 test vectors" { |
| 316 | .msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41", | 317 | .msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41", |
| 317 | .public_key_hex = "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43", | 318 | .public_key_hex = "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43", |
| 318 | .sig_hex = "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f", | 319 | .sig_hex = "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f", |
| 319 | .expected = error.InvalidSignature, // 8 - non-canonical R | 320 | .expected = error.SignatureVerificationFailed, // 8 - non-canonical R |
| 320 | }, | 321 | }, |
| 321 | Vec{ | 322 | Vec{ |
| 322 | .msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41", | 323 | .msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41", |
lib/std/crypto/25519/edwards25519.zig+11-10| ... | @@ -7,6 +7,7 @@ const std = @import("std"); | ... | @@ -7,6 +7,7 @@ const std = @import("std"); |
| 7 | const debug = std.debug; | 7 | const debug = std.debug; |
| 8 | const fmt = std.fmt; | 8 | const fmt = std.fmt; |
| 9 | const mem = std.mem; | 9 | const mem = std.mem; |
| 10 | const Error = std.crypto.Error; | ||
| 10 | 11 | ||
| 11 | /// Group operations over Edwards25519. | 12 | /// Group operations over Edwards25519. |
| 12 | pub const Edwards25519 = struct { | 13 | pub const Edwards25519 = struct { |
| ... | @@ -25,7 +26,7 @@ pub const Edwards25519 = struct { | ... | @@ -25,7 +26,7 @@ pub const Edwards25519 = struct { |
| 25 | is_base: bool = false, | 26 | is_base: bool = false, |
| 26 | 27 | ||
| 27 | /// Decode an Edwards25519 point from its compressed (Y+sign) coordinates. | 28 | /// Decode an Edwards25519 point from its compressed (Y+sign) coordinates. |
| 28 | pub fn fromBytes(s: [encoded_length]u8) !Edwards25519 { | 29 | pub fn fromBytes(s: [encoded_length]u8) Error!Edwards25519 { |
| 29 | const z = Fe.one; | 30 | const z = Fe.one; |
| 30 | const y = Fe.fromBytes(s); | 31 | const y = Fe.fromBytes(s); |
| 31 | var u = y.sq(); | 32 | var u = y.sq(); |
| ... | @@ -55,7 +56,7 @@ pub const Edwards25519 = struct { | ... | @@ -55,7 +56,7 @@ pub const Edwards25519 = struct { |
| 55 | } | 56 | } |
| 56 | 57 | ||
| 57 | /// Check that the encoding of a point is canonical. | 58 | /// Check that the encoding of a point is canonical. |
| 58 | pub fn rejectNonCanonical(s: [32]u8) !void { | 59 | pub fn rejectNonCanonical(s: [32]u8) Error!void { |
| 59 | return Fe.rejectNonCanonical(s, true); | 60 | return Fe.rejectNonCanonical(s, true); |
| 60 | } | 61 | } |
| 61 | 62 | ||
| ... | @@ -80,7 +81,7 @@ pub const Edwards25519 = struct { | ... | @@ -80,7 +81,7 @@ pub const Edwards25519 = struct { |
| 80 | const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero }; | 81 | const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero }; |
| 81 | 82 | ||
| 82 | /// Reject the neutral element. | 83 | /// Reject the neutral element. |
| 83 | pub fn rejectIdentity(p: Edwards25519) !void { | 84 | pub fn rejectIdentity(p: Edwards25519) Error!void { |
| 84 | if (p.x.isZero()) { | 85 | if (p.x.isZero()) { |
| 85 | return error.IdentityElement; | 86 | return error.IdentityElement; |
| 86 | } | 87 | } |
| ... | @@ -176,7 +177,7 @@ pub const Edwards25519 = struct { | ... | @@ -176,7 +177,7 @@ pub const Edwards25519 = struct { |
| 176 | // Based on real-world benchmarks, we only use this for multi-scalar multiplication. | 177 | // Based on real-world benchmarks, we only use this for multi-scalar multiplication. |
| 177 | // NAF could be useful to half the size of precomputation tables, but we intentionally | 178 | // NAF could be useful to half the size of precomputation tables, but we intentionally |
| 178 | // avoid these to keep the standard library lightweight. | 179 | // avoid these to keep the standard library lightweight. |
| 179 | fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) !Edwards25519 { | 180 | fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) Error!Edwards25519 { |
| 180 | std.debug.assert(vartime); | 181 | std.debug.assert(vartime); |
| 181 | const e = nonAdjacentForm(s); | 182 | const e = nonAdjacentForm(s); |
| 182 | var q = Edwards25519.identityElement; | 183 | var q = Edwards25519.identityElement; |
| ... | @@ -196,7 +197,7 @@ pub const Edwards25519 = struct { | ... | @@ -196,7 +197,7 @@ pub const Edwards25519 = struct { |
| 196 | } | 197 | } |
| 197 | 198 | ||
| 198 | // Scalar multiplication with a 4-bit window and the first 15 multiples. | 199 | // Scalar multiplication with a 4-bit window and the first 15 multiples. |
| 199 | fn pcMul16(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) !Edwards25519 { | 200 | fn pcMul16(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) Error!Edwards25519 { |
| 200 | var q = Edwards25519.identityElement; | 201 | var q = Edwards25519.identityElement; |
| 201 | var pos: usize = 252; | 202 | var pos: usize = 252; |
| 202 | while (true) : (pos -= 4) { | 203 | while (true) : (pos -= 4) { |
| ... | @@ -234,7 +235,7 @@ pub const Edwards25519 = struct { | ... | @@ -234,7 +235,7 @@ pub const Edwards25519 = struct { |
| 234 | /// Multiply an Edwards25519 point by a scalar without clamping it. | 235 | /// Multiply an Edwards25519 point by a scalar without clamping it. |
| 235 | /// Return error.WeakPublicKey if the resulting point is | 236 | /// Return error.WeakPublicKey if the resulting point is |
| 236 | /// the identity element. | 237 | /// the identity element. |
| 237 | pub fn mul(p: Edwards25519, s: [32]u8) !Edwards25519 { | 238 | pub fn mul(p: Edwards25519, s: [32]u8) Error!Edwards25519 { |
| 238 | const pc = if (p.is_base) basePointPc else pc: { | 239 | const pc = if (p.is_base) basePointPc else pc: { |
| 239 | const xpc = precompute(p, 15); | 240 | const xpc = precompute(p, 15); |
| 240 | xpc[4].rejectIdentity() catch |_| return error.WeakPublicKey; | 241 | xpc[4].rejectIdentity() catch |_| return error.WeakPublicKey; |
| ... | @@ -245,7 +246,7 @@ pub const Edwards25519 = struct { | ... | @@ -245,7 +246,7 @@ pub const Edwards25519 = struct { |
| 245 | 246 | ||
| 246 | /// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME* | 247 | /// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME* |
| 247 | /// This can be used for signature verification. | 248 | /// This can be used for signature verification. |
| 248 | pub fn mulPublic(p: Edwards25519, s: [32]u8) !Edwards25519 { | 249 | pub fn mulPublic(p: Edwards25519, s: [32]u8) Error!Edwards25519 { |
| 249 | if (p.is_base) { | 250 | if (p.is_base) { |
| 250 | return pcMul16(basePointPc, s, true); | 251 | return pcMul16(basePointPc, s, true); |
| 251 | } else { | 252 | } else { |
| ... | @@ -257,7 +258,7 @@ pub const Edwards25519 = struct { | ... | @@ -257,7 +258,7 @@ pub const Edwards25519 = struct { |
| 257 | 258 | ||
| 258 | /// Multiscalar multiplication *IN VARIABLE TIME* for public data | 259 | /// Multiscalar multiplication *IN VARIABLE TIME* for public data |
| 259 | /// Computes ps0*ss0 + ps1*ss1 + ps2*ss2... faster than doing many of these operations individually | 260 | /// Computes ps0*ss0 + ps1*ss1 + ps2*ss2... faster than doing many of these operations individually |
| 260 | pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) !Edwards25519 { | 261 | pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) Error!Edwards25519 { |
| 261 | var pcs: [count][9]Edwards25519 = undefined; | 262 | var pcs: [count][9]Edwards25519 = undefined; |
| 262 | for (ps) |p, i| { | 263 | for (ps) |p, i| { |
| 263 | if (p.is_base) { | 264 | if (p.is_base) { |
| ... | @@ -296,14 +297,14 @@ pub const Edwards25519 = struct { | ... | @@ -296,14 +297,14 @@ pub const Edwards25519 = struct { |
| 296 | /// This is strongly recommended for DH operations. | 297 | /// This is strongly recommended for DH operations. |
| 297 | /// Return error.WeakPublicKey if the resulting point is | 298 | /// Return error.WeakPublicKey if the resulting point is |
| 298 | /// the identity element. | 299 | /// the identity element. |
| 299 | pub fn clampedMul(p: Edwards25519, s: [32]u8) !Edwards25519 { | 300 | pub fn clampedMul(p: Edwards25519, s: [32]u8) Error!Edwards25519 { |
| 300 | var t: [32]u8 = s; | 301 | var t: [32]u8 = s; |
| 301 | scalar.clamp(&t); | 302 | scalar.clamp(&t); |
| 302 | return mul(p, t); | 303 | return mul(p, t); |
| 303 | } | 304 | } |
| 304 | 305 | ||
| 305 | // montgomery -- recover y = sqrt(x^3 + A*x^2 + x) | 306 | // montgomery -- recover y = sqrt(x^3 + A*x^2 + x) |
| 306 | fn xmontToYmont(x: Fe) !Fe { | 307 | fn xmontToYmont(x: Fe) Error!Fe { |
| 307 | var x2 = x.sq(); | 308 | var x2 = x.sq(); |
| 308 | const x3 = x.mul(x2); | 309 | const x3 = x.mul(x2); |
| 309 | x2 = x2.mul32(Fe.edwards25519a_32); | 310 | x2 = x2.mul32(Fe.edwards25519a_32); |
lib/std/crypto/25519/field.zig+3-2| ... | @@ -6,6 +6,7 @@ | ... | @@ -6,6 +6,7 @@ |
| 6 | const std = @import("std"); | 6 | const std = @import("std"); |
| 7 | const readIntLittle = std.mem.readIntLittle; | 7 | const readIntLittle = std.mem.readIntLittle; |
| 8 | const writeIntLittle = std.mem.writeIntLittle; | 8 | const writeIntLittle = std.mem.writeIntLittle; |
| 9 | const Error = std.crypto.Error; | ||
| 9 | 10 | ||
| 10 | pub const Fe = struct { | 11 | pub const Fe = struct { |
| 11 | limbs: [5]u64, | 12 | limbs: [5]u64, |
| ... | @@ -112,7 +113,7 @@ pub const Fe = struct { | ... | @@ -112,7 +113,7 @@ pub const Fe = struct { |
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | /// Reject non-canonical encodings of an element, possibly ignoring the top bit | 115 | /// Reject non-canonical encodings of an element, possibly ignoring the top bit |
| 115 | pub fn rejectNonCanonical(s: [32]u8, comptime ignore_extra_bit: bool) !void { | 116 | pub fn rejectNonCanonical(s: [32]u8, comptime ignore_extra_bit: bool) Error!void { |
| 116 | var c: u16 = (s[31] & 0x7f) ^ 0x7f; | 117 | var c: u16 = (s[31] & 0x7f) ^ 0x7f; |
| 117 | comptime var i = 30; | 118 | comptime var i = 30; |
| 118 | inline while (i > 0) : (i -= 1) { | 119 | inline while (i > 0) : (i -= 1) { |
| ... | @@ -412,7 +413,7 @@ pub const Fe = struct { | ... | @@ -412,7 +413,7 @@ pub const Fe = struct { |
| 412 | } | 413 | } |
| 413 | 414 | ||
| 414 | /// Compute the square root of `x2`, returning `error.NotSquare` if `x2` was not a square | 415 | /// Compute the square root of `x2`, returning `error.NotSquare` if `x2` was not a square |
| 415 | pub fn sqrt(x2: Fe) !Fe { | 416 | pub fn sqrt(x2: Fe) Error!Fe { |
| 416 | var x2_copy = x2; | 417 | var x2_copy = x2; |
| 417 | const x = x2.uncheckedSqrt(); | 418 | const x = x2.uncheckedSqrt(); |
| 418 | const check = x.sq().sub(x2_copy); | 419 | const check = x.sq().sub(x2_copy); |
lib/std/crypto/25519/ristretto255.zig+5-4| ... | @@ -5,6 +5,7 @@ | ... | @@ -5,6 +5,7 @@ |
| 5 | // and substantial portions of the software. | 5 | // and substantial portions of the software. |
| 6 | const std = @import("std"); | 6 | const std = @import("std"); |
| 7 | const fmt = std.fmt; | 7 | const fmt = std.fmt; |
| 8 | const Error = std.crypto.Error; | ||
| 8 | 9 | ||
| 9 | /// Group operations over Edwards25519. | 10 | /// Group operations over Edwards25519. |
| 10 | pub const Ristretto255 = struct { | 11 | pub const Ristretto255 = struct { |
| ... | @@ -34,7 +35,7 @@ pub const Ristretto255 = struct { | ... | @@ -34,7 +35,7 @@ pub const Ristretto255 = struct { |
| 34 | return .{ .ratio_is_square = @boolToInt(has_m_root) | @boolToInt(has_p_root), .root = x.abs() }; | 35 | return .{ .ratio_is_square = @boolToInt(has_m_root) | @boolToInt(has_p_root), .root = x.abs() }; |
| 35 | } | 36 | } |
| 36 | 37 | ||
| 37 | fn rejectNonCanonical(s: [encoded_length]u8) !void { | 38 | fn rejectNonCanonical(s: [encoded_length]u8) Error!void { |
| 38 | if ((s[0] & 1) != 0) { | 39 | if ((s[0] & 1) != 0) { |
| 39 | return error.NonCanonical; | 40 | return error.NonCanonical; |
| 40 | } | 41 | } |
| ... | @@ -42,7 +43,7 @@ pub const Ristretto255 = struct { | ... | @@ -42,7 +43,7 @@ pub const Ristretto255 = struct { |
| 42 | } | 43 | } |
| 43 | 44 | ||
| 44 | /// Reject the neutral element. | 45 | /// Reject the neutral element. |
| 45 | pub fn rejectIdentity(p: Ristretto255) callconv(.Inline) !void { | 46 | pub fn rejectIdentity(p: Ristretto255) callconv(.Inline) Error!void { |
| 46 | return p.p.rejectIdentity(); | 47 | return p.p.rejectIdentity(); |
| 47 | } | 48 | } |
| 48 | 49 | ||
| ... | @@ -50,7 +51,7 @@ pub const Ristretto255 = struct { | ... | @@ -50,7 +51,7 @@ pub const Ristretto255 = struct { |
| 50 | pub const basePoint = Ristretto255{ .p = Curve.basePoint }; | 51 | pub const basePoint = Ristretto255{ .p = Curve.basePoint }; |
| 51 | 52 | ||
| 52 | /// Decode a Ristretto255 representative. | 53 | /// Decode a Ristretto255 representative. |
| 53 | pub fn fromBytes(s: [encoded_length]u8) !Ristretto255 { | 54 | pub fn fromBytes(s: [encoded_length]u8) Error!Ristretto255 { |
| 54 | try rejectNonCanonical(s); | 55 | try rejectNonCanonical(s); |
| 55 | const s_ = Fe.fromBytes(s); | 56 | const s_ = Fe.fromBytes(s); |
| 56 | const ss = s_.sq(); // s^2 | 57 | const ss = s_.sq(); // s^2 |
| ... | @@ -153,7 +154,7 @@ pub const Ristretto255 = struct { | ... | @@ -153,7 +154,7 @@ pub const Ristretto255 = struct { |
| 153 | /// Multiply a Ristretto255 element with a scalar. | 154 | /// Multiply a Ristretto255 element with a scalar. |
| 154 | /// Return error.WeakPublicKey if the resulting element is | 155 | /// Return error.WeakPublicKey if the resulting element is |
| 155 | /// the identity element. | 156 | /// the identity element. |
| 156 | pub fn mul(p: Ristretto255, s: [encoded_length]u8) callconv(.Inline) !Ristretto255 { | 157 | pub fn mul(p: Ristretto255, s: [encoded_length]u8) callconv(.Inline) Error!Ristretto255 { |
| 157 | return Ristretto255{ .p = try p.p.mul(s) }; | 158 | return Ristretto255{ .p = try p.p.mul(s) }; |
| 158 | } | 159 | } |
| 159 | 160 |
lib/std/crypto/25519/scalar.zig+2-1| ... | @@ -5,6 +5,7 @@ | ... | @@ -5,6 +5,7 @@ |
| 5 | // and substantial portions of the software. | 5 | // and substantial portions of the software. |
| 6 | const std = @import("std"); | 6 | const std = @import("std"); |
| 7 | const mem = std.mem; | 7 | const mem = std.mem; |
| 8 | const Error = std.crypto.Error; | ||
| 8 | 9 | ||
| 9 | /// 2^252 + 27742317777372353535851937790883648493 | 10 | /// 2^252 + 27742317777372353535851937790883648493 |
| 10 | pub const field_size = [32]u8{ | 11 | pub const field_size = [32]u8{ |
| ... | @@ -18,7 +19,7 @@ pub const CompressedScalar = [32]u8; | ... | @@ -18,7 +19,7 @@ pub const CompressedScalar = [32]u8; |
| 18 | pub const zero = [_]u8{0} ** 32; | 19 | pub const zero = [_]u8{0} ** 32; |
| 19 | 20 | ||
| 20 | /// Reject a scalar whose encoding is not canonical. | 21 | /// Reject a scalar whose encoding is not canonical. |
| 21 | pub fn rejectNonCanonical(s: [32]u8) !void { | 22 | pub fn rejectNonCanonical(s: [32]u8) Error!void { |
| 22 | var c: u8 = 0; | 23 | var c: u8 = 0; |
| 23 | var n: u8 = 1; | 24 | var n: u8 = 1; |
| 24 | var i: usize = 31; | 25 | var i: usize = 31; |
lib/std/crypto/25519/x25519.zig+6-5| ... | @@ -9,6 +9,7 @@ const mem = std.mem; | ... | @@ -9,6 +9,7 @@ const mem = std.mem; |
| 9 | const fmt = std.fmt; | 9 | const fmt = std.fmt; |
| 10 | 10 | ||
| 11 | const Sha512 = crypto.hash.sha2.Sha512; | 11 | const Sha512 = crypto.hash.sha2.Sha512; |
| 12 | const Error = crypto.Error; | ||
| 12 | 13 | ||
| 13 | /// X25519 DH function. | 14 | /// X25519 DH function. |
| 14 | pub const X25519 = struct { | 15 | pub const X25519 = struct { |
| ... | @@ -31,7 +32,7 @@ pub const X25519 = struct { | ... | @@ -31,7 +32,7 @@ pub const X25519 = struct { |
| 31 | secret_key: [secret_length]u8, | 32 | secret_key: [secret_length]u8, |
| 32 | 33 | ||
| 33 | /// Create a new key pair using an optional seed. | 34 | /// Create a new key pair using an optional seed. |
| 34 | pub fn create(seed: ?[seed_length]u8) !KeyPair { | 35 | pub fn create(seed: ?[seed_length]u8) Error!KeyPair { |
| 35 | const sk = seed orelse sk: { | 36 | const sk = seed orelse sk: { |
| 36 | var random_seed: [seed_length]u8 = undefined; | 37 | var random_seed: [seed_length]u8 = undefined; |
| 37 | crypto.random.bytes(&random_seed); | 38 | crypto.random.bytes(&random_seed); |
| ... | @@ -44,7 +45,7 @@ pub const X25519 = struct { | ... | @@ -44,7 +45,7 @@ pub const X25519 = struct { |
| 44 | } | 45 | } |
| 45 | 46 | ||
| 46 | /// Create a key pair from an Ed25519 key pair | 47 | /// Create a key pair from an Ed25519 key pair |
| 47 | pub fn fromEd25519(ed25519_key_pair: crypto.sign.Ed25519.KeyPair) !KeyPair { | 48 | pub fn fromEd25519(ed25519_key_pair: crypto.sign.Ed25519.KeyPair) Error!KeyPair { |
| 48 | const seed = ed25519_key_pair.secret_key[0..32]; | 49 | const seed = ed25519_key_pair.secret_key[0..32]; |
| 49 | var az: [Sha512.digest_length]u8 = undefined; | 50 | var az: [Sha512.digest_length]u8 = undefined; |
| 50 | Sha512.hash(seed, &az, .{}); | 51 | Sha512.hash(seed, &az, .{}); |
| ... | @@ -59,13 +60,13 @@ pub const X25519 = struct { | ... | @@ -59,13 +60,13 @@ pub const X25519 = struct { |
| 59 | }; | 60 | }; |
| 60 | 61 | ||
| 61 | /// Compute the public key for a given private key. | 62 | /// Compute the public key for a given private key. |
| 62 | pub fn recoverPublicKey(secret_key: [secret_length]u8) ![public_length]u8 { | 63 | pub fn recoverPublicKey(secret_key: [secret_length]u8) Error![public_length]u8 { |
| 63 | const q = try Curve.basePoint.clampedMul(secret_key); | 64 | const q = try Curve.basePoint.clampedMul(secret_key); |
| 64 | return q.toBytes(); | 65 | return q.toBytes(); |
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | /// Compute the X25519 equivalent to an Ed25519 public eky. | 68 | /// Compute the X25519 equivalent to an Ed25519 public eky. |
| 68 | pub fn publicKeyFromEd25519(ed25519_public_key: [crypto.sign.Ed25519.public_length]u8) ![public_length]u8 { | 69 | pub fn publicKeyFromEd25519(ed25519_public_key: [crypto.sign.Ed25519.public_length]u8) Error![public_length]u8 { |
| 69 | const pk_ed = try crypto.ecc.Edwards25519.fromBytes(ed25519_public_key); | 70 | const pk_ed = try crypto.ecc.Edwards25519.fromBytes(ed25519_public_key); |
| 70 | const pk = try Curve.fromEdwards25519(pk_ed); | 71 | const pk = try Curve.fromEdwards25519(pk_ed); |
| 71 | return pk.toBytes(); | 72 | return pk.toBytes(); |
| ... | @@ -74,7 +75,7 @@ pub const X25519 = struct { | ... | @@ -74,7 +75,7 @@ pub const X25519 = struct { |
| 74 | /// Compute the scalar product of a public key and a secret scalar. | 75 | /// Compute the scalar product of a public key and a secret scalar. |
| 75 | /// Note that the output should not be used as a shared secret without | 76 | /// Note that the output should not be used as a shared secret without |
| 76 | /// hashing it first. | 77 | /// hashing it first. |
| 77 | pub fn scalarmult(secret_key: [secret_length]u8, public_key: [public_length]u8) ![shared_length]u8 { | 78 | pub fn scalarmult(secret_key: [secret_length]u8, public_key: [public_length]u8) Error![shared_length]u8 { |
| 78 | const q = try Curve.fromBytes(public_key).clampedMul(secret_key); | 79 | const q = try Curve.fromBytes(public_key).clampedMul(secret_key); |
| 79 | return q.toBytes(); | 80 | return q.toBytes(); |
| 80 | } | 81 | } |
lib/std/crypto/aegis.zig+3-2| ... | @@ -8,6 +8,7 @@ const std = @import("std"); | ... | @@ -8,6 +8,7 @@ const std = @import("std"); |
| 8 | const mem = std.mem; | 8 | const mem = std.mem; |
| 9 | const assert = std.debug.assert; | 9 | const assert = std.debug.assert; |
| 10 | const AesBlock = std.crypto.core.aes.Block; | 10 | const AesBlock = std.crypto.core.aes.Block; |
| 11 | const Error = std.crypto.Error; | ||
| 11 | 12 | ||
| 12 | const State128L = struct { | 13 | const State128L = struct { |
| 13 | blocks: [8]AesBlock, | 14 | blocks: [8]AesBlock, |
| ... | @@ -136,7 +137,7 @@ pub const Aegis128L = struct { | ... | @@ -136,7 +137,7 @@ pub const Aegis128L = struct { |
| 136 | /// ad: Associated Data | 137 | /// ad: Associated Data |
| 137 | /// npub: public nonce | 138 | /// npub: public nonce |
| 138 | /// k: private key | 139 | /// k: private key |
| 139 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) !void { | 140 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void { |
| 140 | assert(c.len == m.len); | 141 | assert(c.len == m.len); |
| 141 | var state = State128L.init(key, npub); | 142 | var state = State128L.init(key, npub); |
| 142 | var src: [32]u8 align(16) = undefined; | 143 | var src: [32]u8 align(16) = undefined; |
| ... | @@ -298,7 +299,7 @@ pub const Aegis256 = struct { | ... | @@ -298,7 +299,7 @@ pub const Aegis256 = struct { |
| 298 | /// ad: Associated Data | 299 | /// ad: Associated Data |
| 299 | /// npub: public nonce | 300 | /// npub: public nonce |
| 300 | /// k: private key | 301 | /// k: private key |
| 301 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) !void { | 302 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void { |
| 302 | assert(c.len == m.len); | 303 | assert(c.len == m.len); |
| 303 | var state = State256.init(key, npub); | 304 | var state = State256.init(key, npub); |
| 304 | var src: [16]u8 align(16) = undefined; | 305 | var src: [16]u8 align(16) = undefined; |
lib/std/crypto/aes_gcm.zig+2-1| ... | @@ -12,6 +12,7 @@ const debug = std.debug; | ... | @@ -12,6 +12,7 @@ const debug = std.debug; |
| 12 | const Ghash = std.crypto.onetimeauth.Ghash; | 12 | const Ghash = std.crypto.onetimeauth.Ghash; |
| 13 | const mem = std.mem; | 13 | const mem = std.mem; |
| 14 | const modes = crypto.core.modes; | 14 | const modes = crypto.core.modes; |
| 15 | const Error = crypto.Error; | ||
| 15 | 16 | ||
| 16 | pub const Aes128Gcm = AesGcm(crypto.core.aes.Aes128); | 17 | pub const Aes128Gcm = AesGcm(crypto.core.aes.Aes128); |
| 17 | pub const Aes256Gcm = AesGcm(crypto.core.aes.Aes256); | 18 | pub const Aes256Gcm = AesGcm(crypto.core.aes.Aes256); |
| ... | @@ -59,7 +60,7 @@ fn AesGcm(comptime Aes: anytype) type { | ... | @@ -59,7 +60,7 @@ fn AesGcm(comptime Aes: anytype) type { |
| 59 | } | 60 | } |
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) !void { | 63 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void { |
| 63 | assert(c.len == m.len); | 64 | assert(c.len == m.len); |
| 64 | 65 | ||
| 65 | const aes = Aes.initEnc(key); | 66 | const aes = Aes.initEnc(key); |
lib/std/crypto/aes_ocb.zig+2-1| ... | @@ -10,6 +10,7 @@ const aes = crypto.core.aes; | ... | @@ -10,6 +10,7 @@ const aes = crypto.core.aes; |
| 10 | const assert = std.debug.assert; | 10 | const assert = std.debug.assert; |
| 11 | const math = std.math; | 11 | const math = std.math; |
| 12 | const mem = std.mem; | 12 | const mem = std.mem; |
| 13 | const Error = crypto.Error; | ||
| 13 | 14 | ||
| 14 | pub const Aes128Ocb = AesOcb(aes.Aes128); | 15 | pub const Aes128Ocb = AesOcb(aes.Aes128); |
| 15 | pub const Aes256Ocb = AesOcb(aes.Aes256); | 16 | pub const Aes256Ocb = AesOcb(aes.Aes256); |
| ... | @@ -178,7 +179,7 @@ fn AesOcb(comptime Aes: anytype) type { | ... | @@ -178,7 +179,7 @@ fn AesOcb(comptime Aes: anytype) type { |
| 178 | /// ad: Associated Data | 179 | /// ad: Associated Data |
| 179 | /// npub: public nonce | 180 | /// npub: public nonce |
| 180 | /// k: secret key | 181 | /// k: secret key |
| 181 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) !void { | 182 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void { |
| 182 | assert(c.len == m.len); | 183 | assert(c.len == m.len); |
| 183 | 184 | ||
| 184 | const aes_enc_ctx = Aes.initEnc(key); | 185 | const aes_enc_ctx = Aes.initEnc(key); |
lib/std/crypto/bcrypt.zig+8-14| ... | @@ -11,7 +11,8 @@ const math = std.math; | ... | @@ -11,7 +11,8 @@ const math = std.math; |
| 11 | const mem = std.mem; | 11 | const mem = std.mem; |
| 12 | const debug = std.debug; | 12 | const debug = std.debug; |
| 13 | const testing = std.testing; | 13 | const testing = std.testing; |
| 14 | const utils = std.crypto.utils; | 14 | const utils = crypto.utils; |
| 15 | const Error = crypto.Error; | ||
| 15 | 16 | ||
| 16 | const salt_length: usize = 16; | 17 | const salt_length: usize = 16; |
| 17 | const salt_str_length: usize = 22; | 18 | const salt_str_length: usize = 22; |
| ... | @@ -21,13 +22,6 @@ const ct_length: usize = 24; | ... | @@ -21,13 +22,6 @@ const ct_length: usize = 24; |
| 21 | /// Length (in bytes) of a password hash | 22 | /// Length (in bytes) of a password hash |
| 22 | pub const hash_length: usize = 60; | 23 | pub const hash_length: usize = 60; |
| 23 | 24 | ||
| 24 | pub const BcryptError = error{ | ||
| 25 | /// The hashed password cannot be decoded. | ||
| 26 | InvalidEncoding, | ||
| 27 | /// The hash is not valid for the given password. | ||
| 28 | InvalidPassword, | ||
| 29 | }; | ||
| 30 | |||
| 31 | const State = struct { | 25 | const State = struct { |
| 32 | sboxes: [4][256]u32 = [4][256]u32{ | 26 | sboxes: [4][256]u32 = [4][256]u32{ |
| 33 | .{ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a }, | 27 | .{ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a }, |
| ... | @@ -185,7 +179,7 @@ const Codec = struct { | ... | @@ -185,7 +179,7 @@ const Codec = struct { |
| 185 | debug.assert(j == b64.len); | 179 | debug.assert(j == b64.len); |
| 186 | } | 180 | } |
| 187 | 181 | ||
| 188 | fn decode(bin: []u8, b64: []const u8) BcryptError!void { | 182 | fn decode(bin: []u8, b64: []const u8) Error!void { |
| 189 | var i: usize = 0; | 183 | var i: usize = 0; |
| 190 | var j: usize = 0; | 184 | var j: usize = 0; |
| 191 | while (j < bin.len) { | 185 | while (j < bin.len) { |
| ... | @@ -210,7 +204,7 @@ const Codec = struct { | ... | @@ -210,7 +204,7 @@ const Codec = struct { |
| 210 | } | 204 | } |
| 211 | }; | 205 | }; |
| 212 | 206 | ||
| 213 | fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) BcryptError![hash_length]u8 { | 207 | fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) Error![hash_length]u8 { |
| 214 | var state = State{}; | 208 | var state = State{}; |
| 215 | var password_buf: [73]u8 = undefined; | 209 | var password_buf: [73]u8 = undefined; |
| 216 | const trimmed_len = math.min(password.len, password_buf.len - 1); | 210 | const trimmed_len = math.min(password.len, password_buf.len - 1); |
| ... | @@ -258,14 +252,14 @@ fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) | ... | @@ -258,14 +252,14 @@ fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) |
| 258 | /// IMPORTANT: by design, bcrypt silently truncates passwords to 72 bytes. | 252 | /// IMPORTANT: by design, bcrypt silently truncates passwords to 72 bytes. |
| 259 | /// If this is an issue for your application, hash the password first using a function such as SHA-512, | 253 | /// If this is an issue for your application, hash the password first using a function such as SHA-512, |
| 260 | /// and then use the resulting hash as the password parameter for bcrypt. | 254 | /// and then use the resulting hash as the password parameter for bcrypt. |
| 261 | pub fn strHash(password: []const u8, rounds_log: u6) ![hash_length]u8 { | 255 | pub fn strHash(password: []const u8, rounds_log: u6) Error![hash_length]u8 { |
| 262 | var salt: [salt_length]u8 = undefined; | 256 | var salt: [salt_length]u8 = undefined; |
| 263 | crypto.random.bytes(&salt); | 257 | crypto.random.bytes(&salt); |
| 264 | return strHashInternal(password, rounds_log, salt); | 258 | return strHashInternal(password, rounds_log, salt); |
| 265 | } | 259 | } |
| 266 | 260 | ||
| 267 | /// Verify that a previously computed hash is valid for a given password. | 261 | /// Verify that a previously computed hash is valid for a given password. |
| 268 | pub fn strVerify(h: [hash_length]u8, password: []const u8) BcryptError!void { | 262 | pub fn strVerify(h: [hash_length]u8, password: []const u8) Error!void { |
| 269 | if (!mem.eql(u8, "$2", h[0..2])) return error.InvalidEncoding; | 263 | if (!mem.eql(u8, "$2", h[0..2])) return error.InvalidEncoding; |
| 270 | if (h[3] != '$' or h[6] != '$') return error.InvalidEncoding; | 264 | if (h[3] != '$' or h[6] != '$') return error.InvalidEncoding; |
| 271 | const rounds_log_str = h[4..][0..2]; | 265 | const rounds_log_str = h[4..][0..2]; |
| ... | @@ -275,7 +269,7 @@ pub fn strVerify(h: [hash_length]u8, password: []const u8) BcryptError!void { | ... | @@ -275,7 +269,7 @@ pub fn strVerify(h: [hash_length]u8, password: []const u8) BcryptError!void { |
| 275 | const rounds_log = fmt.parseInt(u6, rounds_log_str[0..], 10) catch return error.InvalidEncoding; | 269 | const rounds_log = fmt.parseInt(u6, rounds_log_str[0..], 10) catch return error.InvalidEncoding; |
| 276 | const wanted_s = try strHashInternal(password, rounds_log, salt); | 270 | const wanted_s = try strHashInternal(password, rounds_log, salt); |
| 277 | if (!mem.eql(u8, wanted_s[0..], h[0..])) { | 271 | if (!mem.eql(u8, wanted_s[0..], h[0..])) { |
| 278 | return error.InvalidPassword; | 272 | return error.PasswordVerificationFailed; |
| 279 | } | 273 | } |
| 280 | } | 274 | } |
| 281 | 275 | ||
| ... | @@ -292,7 +286,7 @@ test "bcrypt codec" { | ... | @@ -292,7 +286,7 @@ test "bcrypt codec" { |
| 292 | test "bcrypt" { | 286 | test "bcrypt" { |
| 293 | const s = try strHash("password", 5); | 287 | const s = try strHash("password", 5); |
| 294 | try strVerify(s, "password"); | 288 | try strVerify(s, "password"); |
| 295 | testing.expectError(error.InvalidPassword, strVerify(s, "invalid password")); | 289 | testing.expectError(error.PasswordVerificationFailed, strVerify(s, "invalid password")); |
| 296 | 290 | ||
| 297 | const long_s = try strHash("password" ** 100, 5); | 291 | const long_s = try strHash("password" ** 100, 5); |
| 298 | try strVerify(long_s, "password" ** 100); | 292 | try strVerify(long_s, "password" ** 100); |
lib/std/crypto/chacha20.zig+9-8| ... | @@ -13,6 +13,7 @@ const testing = std.testing; | ... | @@ -13,6 +13,7 @@ const testing = std.testing; |
| 13 | const maxInt = math.maxInt; | 13 | const maxInt = math.maxInt; |
| 14 | const Vector = std.meta.Vector; | 14 | const Vector = std.meta.Vector; |
| 15 | const Poly1305 = std.crypto.onetimeauth.Poly1305; | 15 | const Poly1305 = std.crypto.onetimeauth.Poly1305; |
| 16 | const Error = std.crypto.Error; | ||
| 16 | 17 | ||
| 17 | // Vectorized implementation of the core function | 18 | // Vectorized implementation of the core function |
| 18 | const ChaCha20VecImpl = struct { | 19 | const ChaCha20VecImpl = struct { |
| ... | @@ -656,7 +657,7 @@ fn chacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []c | ... | @@ -656,7 +657,7 @@ fn chacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []c |
| 656 | } | 657 | } |
| 657 | 658 | ||
| 658 | /// Verifies and decrypts an authenticated message produced by chacha20poly1305SealDetached. | 659 | /// Verifies and decrypts an authenticated message produced by chacha20poly1305SealDetached. |
| 659 | fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_length]u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void { | 660 | fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_length]u8, data: []const u8, key: [32]u8, nonce: [12]u8) Error!void { |
| 660 | // split ciphertext and tag | 661 | // split ciphertext and tag |
| 661 | assert(dst.len == ciphertext.len); | 662 | assert(dst.len == ciphertext.len); |
| 662 | 663 | ||
| ... | @@ -702,9 +703,9 @@ fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *const [ | ... | @@ -702,9 +703,9 @@ fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *const [ |
| 702 | } | 703 | } |
| 703 | 704 | ||
| 704 | /// Verifies and decrypts an authenticated message produced by chacha20poly1305Seal. | 705 | /// Verifies and decrypts an authenticated message produced by chacha20poly1305Seal. |
| 705 | fn chacha20poly1305Open(dst: []u8, ciphertextAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void { | 706 | fn chacha20poly1305Open(dst: []u8, ciphertextAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) Error!void { |
| 706 | if (ciphertextAndTag.len < chacha20poly1305_tag_length) { | 707 | if (ciphertextAndTag.len < chacha20poly1305_tag_length) { |
| 707 | return error.InvalidMessage; | 708 | return error.AuthenticationFailed; |
| 708 | } | 709 | } |
| 709 | const ciphertextLen = ciphertextAndTag.len - chacha20poly1305_tag_length; | 710 | const ciphertextLen = ciphertextAndTag.len - chacha20poly1305_tag_length; |
| 710 | return try chacha20poly1305OpenDetached(dst, ciphertextAndTag[0..ciphertextLen], ciphertextAndTag[ciphertextLen..][0..chacha20poly1305_tag_length], data, key, nonce); | 711 | return try chacha20poly1305OpenDetached(dst, ciphertextAndTag[0..ciphertextLen], ciphertextAndTag[ciphertextLen..][0..chacha20poly1305_tag_length], data, key, nonce); |
| ... | @@ -740,13 +741,13 @@ fn xchacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: [] | ... | @@ -740,13 +741,13 @@ fn xchacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: [] |
| 740 | } | 741 | } |
| 741 | 742 | ||
| 742 | /// Verifies and decrypts an authenticated message produced by xchacha20poly1305SealDetached. | 743 | /// Verifies and decrypts an authenticated message produced by xchacha20poly1305SealDetached. |
| 743 | fn xchacha20poly1305OpenDetached(plaintext: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_length]u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void { | 744 | fn xchacha20poly1305OpenDetached(plaintext: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_length]u8, data: []const u8, key: [32]u8, nonce: [24]u8) Error!void { |
| 744 | const extended = extend(key, nonce); | 745 | const extended = extend(key, nonce); |
| 745 | return try chacha20poly1305OpenDetached(plaintext, ciphertext, tag, data, extended.key, extended.nonce); | 746 | return try chacha20poly1305OpenDetached(plaintext, ciphertext, tag, data, extended.key, extended.nonce); |
| 746 | } | 747 | } |
| 747 | 748 | ||
| 748 | /// Verifies and decrypts an authenticated message produced by xchacha20poly1305Seal. | 749 | /// Verifies and decrypts an authenticated message produced by xchacha20poly1305Seal. |
| 749 | fn xchacha20poly1305Open(ciphertextAndTag: []u8, msgAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void { | 750 | fn xchacha20poly1305Open(ciphertextAndTag: []u8, msgAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) Error!void { |
| 750 | const extended = extend(key, nonce); | 751 | const extended = extend(key, nonce); |
| 751 | return try chacha20poly1305Open(ciphertextAndTag, msgAndTag, data, extended.key, extended.nonce); | 752 | return try chacha20poly1305Open(ciphertextAndTag, msgAndTag, data, extended.key, extended.nonce); |
| 752 | } | 753 | } |
| ... | @@ -864,7 +865,7 @@ test "open" { | ... | @@ -864,7 +865,7 @@ test "open" { |
| 864 | testing.expectError(error.AuthenticationFailed, chacha20poly1305Open(out[0..], ciphertext[0..], data[0..], key, bad_nonce)); | 865 | testing.expectError(error.AuthenticationFailed, chacha20poly1305Open(out[0..], ciphertext[0..], data[0..], key, bad_nonce)); |
| 865 | 866 | ||
| 866 | // a short ciphertext should result in a different error | 867 | // a short ciphertext should result in a different error |
| 867 | testing.expectError(error.InvalidMessage, chacha20poly1305Open(out[0..], "", data[0..], key, bad_nonce)); | 868 | testing.expectError(error.AuthenticationFailed, chacha20poly1305Open(out[0..], "", data[0..], key, bad_nonce)); |
| 868 | } | 869 | } |
| 869 | } | 870 | } |
| 870 | 871 | ||
| ... | @@ -915,7 +916,7 @@ pub const Chacha20Poly1305 = struct { | ... | @@ -915,7 +916,7 @@ pub const Chacha20Poly1305 = struct { |
| 915 | /// npub: public nonce | 916 | /// npub: public nonce |
| 916 | /// k: private key | 917 | /// k: private key |
| 917 | /// NOTE: the check of the authentication tag is currently not done in constant time | 918 | /// NOTE: the check of the authentication tag is currently not done in constant time |
| 918 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) !void { | 919 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void { |
| 919 | assert(c.len == m.len); | 920 | assert(c.len == m.len); |
| 920 | return try chacha20poly1305OpenDetached(m, c, tag[0..], ad, k, npub); | 921 | return try chacha20poly1305OpenDetached(m, c, tag[0..], ad, k, npub); |
| 921 | } | 922 | } |
| ... | @@ -944,7 +945,7 @@ pub const XChacha20Poly1305 = struct { | ... | @@ -944,7 +945,7 @@ pub const XChacha20Poly1305 = struct { |
| 944 | /// npub: public nonce | 945 | /// npub: public nonce |
| 945 | /// k: private key | 946 | /// k: private key |
| 946 | /// NOTE: the check of the authentication tag is currently not done in constant time | 947 | /// NOTE: the check of the authentication tag is currently not done in constant time |
| 947 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) !void { | 948 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void { |
| 948 | assert(c.len == m.len); | 949 | assert(c.len == m.len); |
| 949 | return try xchacha20poly1305OpenDetached(m, c, tag[0..], ad, k, npub); | 950 | return try xchacha20poly1305OpenDetached(m, c, tag[0..], ad, k, npub); |
| 950 | } | 951 | } |
lib/std/crypto/error.zig created+34| ... | @@ -0,0 +1,34 @@ | ||
| 1 | pub const Error = error{ | ||
| 2 | /// MAC verification failed - The tag doesn't verify for the given ciphertext and secret key | ||
| 3 | AuthenticationFailed, | ||
| 4 | |||
| 5 | /// The requested output length is too long for the chosen algorithm | ||
| 6 | OutputTooLong, | ||
| 7 | |||
| 8 | /// Finite field operation returned the identity element | ||
| 9 | IdentityElement, | ||
| 10 | |||
| 11 | /// Encoded input cannot be decoded | ||
| 12 | InvalidEncoding, | ||
| 13 | |||
| 14 | /// The signature does't verify for the given message and public key | ||
| 15 | SignatureVerificationFailed, | ||
| 16 | |||
| 17 | /// Both a public and secret key have been provided, but they are incompatible | ||
| 18 | KeyMismatch, | ||
| 19 | |||
| 20 | /// Encoded input is not in canonical form | ||
| 21 | NonCanonical, | ||
| 22 | |||
| 23 | /// Square root has no solutions | ||
| 24 | NotSquare, | ||
| 25 | |||
| 26 | /// Verification string doesn't match the provided password and parameters | ||
| 27 | PasswordVerificationFailed, | ||
| 28 | |||
| 29 | /// Parameters would be insecure to use | ||
| 30 | WeakParameters, | ||
| 31 | |||
| 32 | /// Public key would be insecure to use | ||
| 33 | WeakPublicKey, | ||
| 34 | }; | ||
lib/std/crypto/gimli.zig+3-2| ... | @@ -20,6 +20,7 @@ const assert = std.debug.assert; | ... | @@ -20,6 +20,7 @@ const assert = std.debug.assert; |
| 20 | const testing = std.testing; | 20 | const testing = std.testing; |
| 21 | const htest = @import("test.zig"); | 21 | const htest = @import("test.zig"); |
| 22 | const Vector = std.meta.Vector; | 22 | const Vector = std.meta.Vector; |
| 23 | const Error = std.crypto.Error; | ||
| 23 | 24 | ||
| 24 | pub const State = struct { | 25 | pub const State = struct { |
| 25 | pub const BLOCKBYTES = 48; | 26 | pub const BLOCKBYTES = 48; |
| ... | @@ -392,7 +393,7 @@ pub const Aead = struct { | ... | @@ -392,7 +393,7 @@ pub const Aead = struct { |
| 392 | /// npub: public nonce | 393 | /// npub: public nonce |
| 393 | /// k: private key | 394 | /// k: private key |
| 394 | /// NOTE: the check of the authentication tag is currently not done in constant time | 395 | /// NOTE: the check of the authentication tag is currently not done in constant time |
| 395 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) !void { | 396 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void { |
| 396 | assert(c.len == m.len); | 397 | assert(c.len == m.len); |
| 397 | 398 | ||
| 398 | var state = Aead.init(ad, npub, k); | 399 | var state = Aead.init(ad, npub, k); |
| ... | @@ -429,7 +430,7 @@ pub const Aead = struct { | ... | @@ -429,7 +430,7 @@ pub const Aead = struct { |
| 429 | // TODO: use a constant-time equality check here, see https://github.com/ziglang/zig/issues/1776 | 430 | // TODO: use a constant-time equality check here, see https://github.com/ziglang/zig/issues/1776 |
| 430 | if (!mem.eql(u8, buf[0..State.RATE], &tag)) { | 431 | if (!mem.eql(u8, buf[0..State.RATE], &tag)) { |
| 431 | @memset(m.ptr, undefined, m.len); | 432 | @memset(m.ptr, undefined, m.len); |
| 432 | return error.InvalidMessage; | 433 | return error.AuthenticationFailed; |
| 433 | } | 434 | } |
| 434 | } | 435 | } |
| 435 | }; | 436 | }; |
lib/std/crypto/isap.zig+2-1| ... | @@ -3,6 +3,7 @@ const debug = std.debug; | ... | @@ -3,6 +3,7 @@ const debug = std.debug; |
| 3 | const mem = std.mem; | 3 | const mem = std.mem; |
| 4 | const math = std.math; | 4 | const math = std.math; |
| 5 | const testing = std.testing; | 5 | const testing = std.testing; |
| 6 | const Error = std.crypto.Error; | ||
| 6 | 7 | ||
| 7 | /// ISAPv2 is an authenticated encryption system hardened against side channels and fault attacks. | 8 | /// ISAPv2 is an authenticated encryption system hardened against side channels and fault attacks. |
| 8 | /// https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/round-2/spec-doc-rnd2/isap-spec-round2.pdf | 9 | /// https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/round-2/spec-doc-rnd2/isap-spec-round2.pdf |
| ... | @@ -217,7 +218,7 @@ pub const IsapA128A = struct { | ... | @@ -217,7 +218,7 @@ pub const IsapA128A = struct { |
| 217 | tag.* = mac(c, ad, npub, key); | 218 | tag.* = mac(c, ad, npub, key); |
| 218 | } | 219 | } |
| 219 | 220 | ||
| 220 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) !void { | 221 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void { |
| 221 | var computed_tag = mac(c, ad, npub, key); | 222 | var computed_tag = mac(c, ad, npub, key); |
| 222 | var acc: u8 = 0; | 223 | var acc: u8 = 0; |
| 223 | for (computed_tag) |_, j| { | 224 | for (computed_tag) |_, j| { |
lib/std/crypto/pbkdf2.zig+4-11| ... | @@ -7,6 +7,7 @@ | ... | @@ -7,6 +7,7 @@ |
| 7 | const std = @import("std"); | 7 | const std = @import("std"); |
| 8 | const mem = std.mem; | 8 | const mem = std.mem; |
| 9 | const maxInt = std.math.maxInt; | 9 | const maxInt = std.math.maxInt; |
| 10 | const Error = std.crypto.Error; | ||
| 10 | 11 | ||
| 11 | // RFC 2898 Section 5.2 | 12 | // RFC 2898 Section 5.2 |
| 12 | // | 13 | // |
| ... | @@ -36,14 +37,6 @@ const maxInt = std.math.maxInt; | ... | @@ -36,14 +37,6 @@ const maxInt = std.math.maxInt; |
| 36 | 37 | ||
| 37 | // Based on Apple's CommonKeyDerivation, based originally on code by Damien Bergamini. | 38 | // Based on Apple's CommonKeyDerivation, based originally on code by Damien Bergamini. |
| 38 | 39 | ||
| 39 | pub const Pbkdf2Error = error{ | ||
| 40 | /// At least one round is required | ||
| 41 | TooFewRounds, | ||
| 42 | |||
| 43 | /// Maximum length of the derived key is `maxInt(u32) * Prf.mac_length` | ||
| 44 | DerivedKeyTooLong, | ||
| 45 | }; | ||
| 46 | |||
| 47 | /// Apply PBKDF2 to generate a key from a password. | 40 | /// Apply PBKDF2 to generate a key from a password. |
| 48 | /// | 41 | /// |
| 49 | /// PBKDF2 is defined in RFC 2898, and is a recommendation of NIST SP 800-132. | 42 | /// PBKDF2 is defined in RFC 2898, and is a recommendation of NIST SP 800-132. |
| ... | @@ -62,8 +55,8 @@ pub const Pbkdf2Error = error{ | ... | @@ -62,8 +55,8 @@ pub const Pbkdf2Error = error{ |
| 62 | /// the derivedKey. It is common to tune this parameter to achieve approximately 100ms. | 55 | /// the derivedKey. It is common to tune this parameter to achieve approximately 100ms. |
| 63 | /// | 56 | /// |
| 64 | /// Prf: Pseudo-random function to use. A common choice is `std.crypto.auth.hmac.HmacSha256`. | 57 | /// Prf: Pseudo-random function to use. A common choice is `std.crypto.auth.hmac.HmacSha256`. |
| 65 | pub fn pbkdf2(derivedKey: []u8, password: []const u8, salt: []const u8, rounds: u32, comptime Prf: type) Pbkdf2Error!void { | 58 | pub fn pbkdf2(derivedKey: []u8, password: []const u8, salt: []const u8, rounds: u32, comptime Prf: type) Error!void { |
| 66 | if (rounds < 1) return error.TooFewRounds; | 59 | if (rounds < 1) return error.WeakParameters; |
| 67 | 60 | ||
| 68 | const dkLen = derivedKey.len; | 61 | const dkLen = derivedKey.len; |
| 69 | const hLen = Prf.mac_length; | 62 | const hLen = Prf.mac_length; |
| ... | @@ -76,7 +69,7 @@ pub fn pbkdf2(derivedKey: []u8, password: []const u8, salt: []const u8, rounds: | ... | @@ -76,7 +69,7 @@ pub fn pbkdf2(derivedKey: []u8, password: []const u8, salt: []const u8, rounds: |
| 76 | // | 69 | // |
| 77 | if (comptime (maxInt(usize) > maxInt(u32) * hLen) and (dkLen > @as(usize, maxInt(u32) * hLen))) { | 70 | if (comptime (maxInt(usize) > maxInt(u32) * hLen) and (dkLen > @as(usize, maxInt(u32) * hLen))) { |
| 78 | // If maxInt(usize) is less than `maxInt(u32) * hLen` then dkLen is always inbounds | 71 | // If maxInt(usize) is less than `maxInt(u32) * hLen` then dkLen is always inbounds |
| 79 | return error.DerivedKeyTooLong; | 72 | return error.OutputTooLong; |
| 80 | } | 73 | } |
| 81 | 74 | ||
| 82 | // FromSpec: | 75 | // FromSpec: |
lib/std/crypto/salsa20.zig+8-7| ... | @@ -15,6 +15,7 @@ const Vector = std.meta.Vector; | ... | @@ -15,6 +15,7 @@ const Vector = std.meta.Vector; |
| 15 | const Poly1305 = crypto.onetimeauth.Poly1305; | 15 | const Poly1305 = crypto.onetimeauth.Poly1305; |
| 16 | const Blake2b = crypto.hash.blake2.Blake2b; | 16 | const Blake2b = crypto.hash.blake2.Blake2b; |
| 17 | const X25519 = crypto.dh.X25519; | 17 | const X25519 = crypto.dh.X25519; |
| 18 | const Error = crypto.Error; | ||
| 18 | 19 | ||
| 19 | const Salsa20VecImpl = struct { | 20 | const Salsa20VecImpl = struct { |
| 20 | const Lane = Vector(4, u32); | 21 | const Lane = Vector(4, u32); |
| ... | @@ -398,7 +399,7 @@ pub const XSalsa20Poly1305 = struct { | ... | @@ -398,7 +399,7 @@ pub const XSalsa20Poly1305 = struct { |
| 398 | /// ad: Associated Data | 399 | /// ad: Associated Data |
| 399 | /// npub: public nonce | 400 | /// npub: public nonce |
| 400 | /// k: private key | 401 | /// k: private key |
| 401 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) !void { | 402 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void { |
| 402 | debug.assert(c.len == m.len); | 403 | debug.assert(c.len == m.len); |
| 403 | const extended = extend(k, npub); | 404 | const extended = extend(k, npub); |
| 404 | var block0 = [_]u8{0} ** 64; | 405 | var block0 = [_]u8{0} ** 64; |
| ... | @@ -446,7 +447,7 @@ pub const SecretBox = struct { | ... | @@ -446,7 +447,7 @@ pub const SecretBox = struct { |
| 446 | 447 | ||
| 447 | /// Verify and decrypt `c` using a nonce `npub` and a key `k`. | 448 | /// Verify and decrypt `c` using a nonce `npub` and a key `k`. |
| 448 | /// `m` must be exactly `tag_length` smaller than `c`, as `c` includes an authentication tag in addition to the encrypted message. | 449 | /// `m` must be exactly `tag_length` smaller than `c`, as `c` includes an authentication tag in addition to the encrypted message. |
| 449 | pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, k: [key_length]u8) !void { | 450 | pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void { |
| 450 | if (c.len < tag_length) { | 451 | if (c.len < tag_length) { |
| 451 | return error.AuthenticationFailed; | 452 | return error.AuthenticationFailed; |
| 452 | } | 453 | } |
| ... | @@ -481,20 +482,20 @@ pub const Box = struct { | ... | @@ -481,20 +482,20 @@ pub const Box = struct { |
| 481 | pub const KeyPair = X25519.KeyPair; | 482 | pub const KeyPair = X25519.KeyPair; |
| 482 | 483 | ||
| 483 | /// Compute a secret suitable for `secretbox` given a recipent's public key and a sender's secret key. | 484 | /// Compute a secret suitable for `secretbox` given a recipent's public key and a sender's secret key. |
| 484 | pub fn createSharedSecret(public_key: [public_length]u8, secret_key: [secret_length]u8) ![shared_length]u8 { | 485 | pub fn createSharedSecret(public_key: [public_length]u8, secret_key: [secret_length]u8) Error![shared_length]u8 { |
| 485 | const p = try X25519.scalarmult(secret_key, public_key); | 486 | const p = try X25519.scalarmult(secret_key, public_key); |
| 486 | const zero = [_]u8{0} ** 16; | 487 | const zero = [_]u8{0} ** 16; |
| 487 | return Salsa20Impl.hsalsa20(zero, p); | 488 | return Salsa20Impl.hsalsa20(zero, p); |
| 488 | } | 489 | } |
| 489 | 490 | ||
| 490 | /// Encrypt and authenticate a message using a recipient's public key `public_key` and a sender's `secret_key`. | 491 | /// Encrypt and authenticate a message using a recipient's public key `public_key` and a sender's `secret_key`. |
| 491 | pub fn seal(c: []u8, m: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) !void { | 492 | pub fn seal(c: []u8, m: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) Error!void { |
| 492 | const shared_key = try createSharedSecret(public_key, secret_key); | 493 | const shared_key = try createSharedSecret(public_key, secret_key); |
| 493 | return SecretBox.seal(c, m, npub, shared_key); | 494 | return SecretBox.seal(c, m, npub, shared_key); |
| 494 | } | 495 | } |
| 495 | 496 | ||
| 496 | /// Verify and decrypt a message using a recipient's secret key `public_key` and a sender's `public_key`. | 497 | /// Verify and decrypt a message using a recipient's secret key `public_key` and a sender's `public_key`. |
| 497 | pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) !void { | 498 | pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) Error!void { |
| 498 | const shared_key = try createSharedSecret(public_key, secret_key); | 499 | const shared_key = try createSharedSecret(public_key, secret_key); |
| 499 | return SecretBox.open(m, c, npub, shared_key); | 500 | return SecretBox.open(m, c, npub, shared_key); |
| 500 | } | 501 | } |
| ... | @@ -527,7 +528,7 @@ pub const SealedBox = struct { | ... | @@ -527,7 +528,7 @@ pub const SealedBox = struct { |
| 527 | 528 | ||
| 528 | /// Encrypt a message `m` for a recipient whose public key is `public_key`. | 529 | /// Encrypt a message `m` for a recipient whose public key is `public_key`. |
| 529 | /// `c` must be `seal_length` bytes larger than `m`, so that the required metadata can be added. | 530 | /// `c` must be `seal_length` bytes larger than `m`, so that the required metadata can be added. |
| 530 | pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) !void { | 531 | pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) Error!void { |
| 531 | debug.assert(c.len == m.len + seal_length); | 532 | debug.assert(c.len == m.len + seal_length); |
| 532 | var ekp = try KeyPair.create(null); | 533 | var ekp = try KeyPair.create(null); |
| 533 | const nonce = createNonce(ekp.public_key, public_key); | 534 | const nonce = createNonce(ekp.public_key, public_key); |
| ... | @@ -538,7 +539,7 @@ pub const SealedBox = struct { | ... | @@ -538,7 +539,7 @@ pub const SealedBox = struct { |
| 538 | 539 | ||
| 539 | /// Decrypt a message using a key pair. | 540 | /// Decrypt a message using a key pair. |
| 540 | /// `m` must be exactly `seal_length` bytes smaller than `c`, as `c` also includes metadata. | 541 | /// `m` must be exactly `seal_length` bytes smaller than `c`, as `c` also includes metadata. |
| 541 | pub fn open(m: []u8, c: []const u8, keypair: KeyPair) !void { | 542 | pub fn open(m: []u8, c: []const u8, keypair: KeyPair) Error!void { |
| 542 | if (c.len < seal_length) { | 543 | if (c.len < seal_length) { |
| 543 | return error.AuthenticationFailed; | 544 | return error.AuthenticationFailed; |
| 544 | } | 545 | } |