diff options
| author | Frank Denis <github@pureftpd.org> | 2021-03-13 15:11:35 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2021-03-14 20:51:31 +0100 |
| commit | b98d7747fa7fb86d5f3f9bdbd00901e16fc58fca (patch) | |
| tree | 4c054a9bfb1c0d53f5d57a297974e5e0255dc026 /lib/std | |
| parent | f69305f865c346ffb2a00403efd0768f8bbdd20b (diff) | |
| download | zig-b98d7747fa7fb86d5f3f9bdbd00901e16fc58fca.tar.gz zig-b98d7747fa7fb86d5f3f9bdbd00901e16fc58fca.zip | |
Use a unified error set for std/crypto/*
This ensures that errors are used consistently across all operations.
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/crypto.zig | 6 | ||||
| -rw-r--r-- | lib/std/crypto/25519/curve25519.zig | 13 | ||||
| -rw-r--r-- | lib/std/crypto/25519/ed25519.zig | 23 | ||||
| -rw-r--r-- | lib/std/crypto/25519/edwards25519.zig | 21 | ||||
| -rw-r--r-- | lib/std/crypto/25519/field.zig | 5 | ||||
| -rw-r--r-- | lib/std/crypto/25519/ristretto255.zig | 9 | ||||
| -rw-r--r-- | lib/std/crypto/25519/scalar.zig | 3 | ||||
| -rw-r--r-- | lib/std/crypto/25519/x25519.zig | 11 | ||||
| -rw-r--r-- | lib/std/crypto/aegis.zig | 5 | ||||
| -rw-r--r-- | lib/std/crypto/aes_gcm.zig | 3 | ||||
| -rw-r--r-- | lib/std/crypto/aes_ocb.zig | 3 | ||||
| -rw-r--r-- | lib/std/crypto/bcrypt.zig | 22 | ||||
| -rw-r--r-- | lib/std/crypto/chacha20.zig | 17 | ||||
| -rw-r--r-- | lib/std/crypto/error.zig | 34 | ||||
| -rw-r--r-- | lib/std/crypto/gimli.zig | 5 | ||||
| -rw-r--r-- | lib/std/crypto/isap.zig | 3 | ||||
| -rw-r--r-- | lib/std/crypto/pbkdf2.zig | 15 | ||||
| -rw-r--r-- | lib/std/crypto/salsa20.zig | 15 |
18 files changed, 126 insertions, 87 deletions
diff --git a/lib/std/crypto.zig b/lib/std/crypto.zig index 24ca549479..1ec7674999 100644 --- a/lib/std/crypto.zig +++ b/lib/std/crypto.zig @@ -144,6 +144,8 @@ pub const random = &@import("crypto/tlcsprng.zig").interface; const std = @import("std.zig"); +pub const Error = @import("crypto/error.zig").Error; + test "crypto" { const please_windows_dont_oom = std.Target.current.os.tag == .windows; if (please_windows_dont_oom) return error.SkipZigTest; @@ -151,7 +153,9 @@ test "crypto" { inline for (std.meta.declarations(@This())) |decl| { switch (decl.data) { .Type => |t| { - std.testing.refAllDecls(t); + if (@typeInfo(t) != .ErrorSet) { + std.testing.refAllDecls(t); + } }, .Var => |v| { _ = v; diff --git a/lib/std/crypto/25519/curve25519.zig b/lib/std/crypto/25519/curve25519.zig index e01b024360..d3e51ad0e0 100644 --- a/lib/std/crypto/25519/curve25519.zig +++ b/lib/std/crypto/25519/curve25519.zig @@ -4,6 +4,7 @@ // The MIT license requires this copyright notice to be included in all copies // and substantial portions of the software. const std = @import("std"); +const Error = std.crypto.Error; /// Group operations over Curve25519. pub const Curve25519 = struct { @@ -28,12 +29,12 @@ pub const Curve25519 = struct { pub const basePoint = Curve25519{ .x = Fe.curve25519BasePoint }; /// Check that the encoding of a Curve25519 point is canonical. - pub fn rejectNonCanonical(s: [32]u8) !void { + pub fn rejectNonCanonical(s: [32]u8) Error!void { return Fe.rejectNonCanonical(s, false); } /// Reject the neutral element. - pub fn rejectIdentity(p: Curve25519) !void { + pub fn rejectIdentity(p: Curve25519) Error!void { if (p.x.isZero()) { return error.IdentityElement; } @@ -44,7 +45,7 @@ pub const Curve25519 = struct { return p.dbl().dbl().dbl(); } - fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) !Curve25519 { + fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) Error!Curve25519 { var x1 = p.x; var x2 = Fe.one; var z2 = Fe.zero; @@ -85,7 +86,7 @@ pub const Curve25519 = struct { /// way to use Curve25519 for a DH operation. /// Return error.IdentityElement if the resulting point is /// the identity element. - pub fn clampedMul(p: Curve25519, s: [32]u8) !Curve25519 { + pub fn clampedMul(p: Curve25519, s: [32]u8) Error!Curve25519 { var t: [32]u8 = s; scalar.clamp(&t); return try ladder(p, t, 255); @@ -95,14 +96,14 @@ pub const Curve25519 = struct { /// Return error.IdentityElement if the resulting point is /// the identity element or error.WeakPublicKey if the public /// key is a low-order point. - pub fn mul(p: Curve25519, s: [32]u8) !Curve25519 { + pub fn mul(p: Curve25519, s: [32]u8) Error!Curve25519 { const cofactor = [_]u8{8} ++ [_]u8{0} ** 31; _ = ladder(p, cofactor, 4) catch |_| return error.WeakPublicKey; return try ladder(p, s, 256); } /// Compute the Curve25519 equivalent to an Edwards25519 point. - pub fn fromEdwards25519(p: std.crypto.ecc.Edwards25519) !Curve25519 { + pub fn fromEdwards25519(p: std.crypto.ecc.Edwards25519) Error!Curve25519 { try p.clearCofactor().rejectIdentity(); const one = std.crypto.ecc.Edwards25519.Fe.one; const x = one.add(p.y).mul(one.sub(p.y).invert()); // xMont=(1+yEd)/(1-yEd) diff --git a/lib/std/crypto/25519/ed25519.zig b/lib/std/crypto/25519/ed25519.zig index 06a4826f58..e385e34f12 100644 --- a/lib/std/crypto/25519/ed25519.zig +++ b/lib/std/crypto/25519/ed25519.zig @@ -8,7 +8,8 @@ const crypto = std.crypto; const debug = std.debug; const fmt = std.fmt; const mem = std.mem; -const Sha512 = std.crypto.hash.sha2.Sha512; +const Sha512 = crypto.hash.sha2.Sha512; +const Error = crypto.Error; /// Ed25519 (EdDSA) signatures. pub const Ed25519 = struct { @@ -40,7 +41,7 @@ pub const Ed25519 = struct { /// /// For this reason, an EdDSA secret key is commonly called a seed, /// from which the actual secret is derived. - pub fn create(seed: ?[seed_length]u8) !KeyPair { + pub fn create(seed: ?[seed_length]u8) Error!KeyPair { const ss = seed orelse ss: { var random_seed: [seed_length]u8 = undefined; crypto.random.bytes(&random_seed); @@ -71,7 +72,7 @@ pub const Ed25519 = struct { /// Sign a message using a key pair, and optional random noise. /// Having noise creates non-standard, non-deterministic signatures, /// but has been proven to increase resilience against fault attacks. - pub fn sign(msg: []const u8, key_pair: KeyPair, noise: ?[noise_length]u8) ![signature_length]u8 { + pub fn sign(msg: []const u8, key_pair: KeyPair, noise: ?[noise_length]u8) Error![signature_length]u8 { const seed = key_pair.secret_key[0..seed_length]; const public_key = key_pair.secret_key[seed_length..]; if (!mem.eql(u8, public_key, &key_pair.public_key)) { @@ -111,8 +112,8 @@ pub const Ed25519 = struct { } /// Verify an Ed25519 signature given a message and a public key. - /// Returns error.InvalidSignature is the signature verification failed. - pub fn verify(sig: [signature_length]u8, msg: []const u8, public_key: [public_length]u8) !void { + /// Returns error.SignatureVerificationFailed is the signature verification failed. + pub fn verify(sig: [signature_length]u8, msg: []const u8, public_key: [public_length]u8) Error!void { const r = sig[0..32]; const s = sig[32..64]; try Curve.scalar.rejectNonCanonical(s.*); @@ -133,7 +134,7 @@ pub const Ed25519 = struct { const ah = try a.neg().mulPublic(hram); const sb_ah = (try Curve.basePoint.mulPublic(s.*)).add(ah); if (expected_r.sub(sb_ah).clearCofactor().rejectIdentity()) |_| { - return error.InvalidSignature; + return error.SignatureVerificationFailed; } else |_| {} } @@ -145,7 +146,7 @@ pub const Ed25519 = struct { }; /// Verify several signatures in a single operation, much faster than verifying signatures one-by-one - pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) !void { + pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) Error!void { var r_batch: [count][32]u8 = undefined; var s_batch: [count][32]u8 = undefined; var a_batch: [count]Curve = undefined; @@ -200,7 +201,7 @@ pub const Ed25519 = struct { const zsb = try Curve.basePoint.mulPublic(zs_sum); if (zr.add(zah).sub(zsb).rejectIdentity()) |_| { - return error.InvalidSignature; + return error.SignatureVerificationFailed; } else |_| {} } }; @@ -223,7 +224,7 @@ test "ed25519 signature" { var buf: [128]u8 = undefined; std.testing.expectEqualStrings(try std.fmt.bufPrint(&buf, "{s}", .{std.fmt.fmtSliceHexUpper(&sig)}), "10A442B4A80CC4225B154F43BEF28D2472CA80221951262EB8E0DF9091575E2687CC486E77263C3418C757522D54F84B0359236ABBBD4ACD20DC297FDCA66808"); try Ed25519.verify(sig, "test", key_pair.public_key); - std.testing.expectError(error.InvalidSignature, Ed25519.verify(sig, "TEST", key_pair.public_key)); + std.testing.expectError(error.SignatureVerificationFailed, Ed25519.verify(sig, "TEST", key_pair.public_key)); } test "ed25519 batch verification" { @@ -251,7 +252,7 @@ test "ed25519 batch verification" { try Ed25519.verifyBatch(2, signature_batch); signature_batch[1].sig = sig1; - std.testing.expectError(error.InvalidSignature, Ed25519.verifyBatch(signature_batch.len, signature_batch)); + std.testing.expectError(error.SignatureVerificationFailed, Ed25519.verifyBatch(signature_batch.len, signature_batch)); } } @@ -316,7 +317,7 @@ test "ed25519 test vectors" { .msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41", .public_key_hex = "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43", .sig_hex = "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f", - .expected = error.InvalidSignature, // 8 - non-canonical R + .expected = error.SignatureVerificationFailed, // 8 - non-canonical R }, Vec{ .msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41", diff --git a/lib/std/crypto/25519/edwards25519.zig b/lib/std/crypto/25519/edwards25519.zig index 8d9922d80c..89b7b9b9f3 100644 --- a/lib/std/crypto/25519/edwards25519.zig +++ b/lib/std/crypto/25519/edwards25519.zig @@ -7,6 +7,7 @@ const std = @import("std"); const debug = std.debug; const fmt = std.fmt; const mem = std.mem; +const Error = std.crypto.Error; /// Group operations over Edwards25519. pub const Edwards25519 = struct { @@ -25,7 +26,7 @@ pub const Edwards25519 = struct { is_base: bool = false, /// Decode an Edwards25519 point from its compressed (Y+sign) coordinates. - pub fn fromBytes(s: [encoded_length]u8) !Edwards25519 { + pub fn fromBytes(s: [encoded_length]u8) Error!Edwards25519 { const z = Fe.one; const y = Fe.fromBytes(s); var u = y.sq(); @@ -55,7 +56,7 @@ pub const Edwards25519 = struct { } /// Check that the encoding of a point is canonical. - pub fn rejectNonCanonical(s: [32]u8) !void { + pub fn rejectNonCanonical(s: [32]u8) Error!void { return Fe.rejectNonCanonical(s, true); } @@ -80,7 +81,7 @@ pub const Edwards25519 = struct { const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero }; /// Reject the neutral element. - pub fn rejectIdentity(p: Edwards25519) !void { + pub fn rejectIdentity(p: Edwards25519) Error!void { if (p.x.isZero()) { return error.IdentityElement; } @@ -176,7 +177,7 @@ pub const Edwards25519 = struct { // Based on real-world benchmarks, we only use this for multi-scalar multiplication. // NAF could be useful to half the size of precomputation tables, but we intentionally // avoid these to keep the standard library lightweight. - fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) !Edwards25519 { + fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) Error!Edwards25519 { std.debug.assert(vartime); const e = nonAdjacentForm(s); var q = Edwards25519.identityElement; @@ -196,7 +197,7 @@ pub const Edwards25519 = struct { } // Scalar multiplication with a 4-bit window and the first 15 multiples. - fn pcMul16(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) !Edwards25519 { + fn pcMul16(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) Error!Edwards25519 { var q = Edwards25519.identityElement; var pos: usize = 252; while (true) : (pos -= 4) { @@ -234,7 +235,7 @@ pub const Edwards25519 = struct { /// Multiply an Edwards25519 point by a scalar without clamping it. /// Return error.WeakPublicKey if the resulting point is /// the identity element. - pub fn mul(p: Edwards25519, s: [32]u8) !Edwards25519 { + pub fn mul(p: Edwards25519, s: [32]u8) Error!Edwards25519 { const pc = if (p.is_base) basePointPc else pc: { const xpc = precompute(p, 15); xpc[4].rejectIdentity() catch |_| return error.WeakPublicKey; @@ -245,7 +246,7 @@ pub const Edwards25519 = struct { /// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME* /// This can be used for signature verification. - pub fn mulPublic(p: Edwards25519, s: [32]u8) !Edwards25519 { + pub fn mulPublic(p: Edwards25519, s: [32]u8) Error!Edwards25519 { if (p.is_base) { return pcMul16(basePointPc, s, true); } else { @@ -257,7 +258,7 @@ pub const Edwards25519 = struct { /// Multiscalar multiplication *IN VARIABLE TIME* for public data /// Computes ps0*ss0 + ps1*ss1 + ps2*ss2... faster than doing many of these operations individually - pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) !Edwards25519 { + pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) Error!Edwards25519 { var pcs: [count][9]Edwards25519 = undefined; for (ps) |p, i| { if (p.is_base) { @@ -296,14 +297,14 @@ pub const Edwards25519 = struct { /// This is strongly recommended for DH operations. /// Return error.WeakPublicKey if the resulting point is /// the identity element. - pub fn clampedMul(p: Edwards25519, s: [32]u8) !Edwards25519 { + pub fn clampedMul(p: Edwards25519, s: [32]u8) Error!Edwards25519 { var t: [32]u8 = s; scalar.clamp(&t); return mul(p, t); } // montgomery -- recover y = sqrt(x^3 + A*x^2 + x) - fn xmontToYmont(x: Fe) !Fe { + fn xmontToYmont(x: Fe) Error!Fe { var x2 = x.sq(); const x3 = x.mul(x2); x2 = x2.mul32(Fe.edwards25519a_32); diff --git a/lib/std/crypto/25519/field.zig b/lib/std/crypto/25519/field.zig index 320cb1bb51..b570e2d06b 100644 --- a/lib/std/crypto/25519/field.zig +++ b/lib/std/crypto/25519/field.zig @@ -6,6 +6,7 @@ const std = @import("std"); const readIntLittle = std.mem.readIntLittle; const writeIntLittle = std.mem.writeIntLittle; +const Error = std.crypto.Error; pub const Fe = struct { limbs: [5]u64, @@ -112,7 +113,7 @@ pub const Fe = struct { } /// Reject non-canonical encodings of an element, possibly ignoring the top bit - pub fn rejectNonCanonical(s: [32]u8, comptime ignore_extra_bit: bool) !void { + pub fn rejectNonCanonical(s: [32]u8, comptime ignore_extra_bit: bool) Error!void { var c: u16 = (s[31] & 0x7f) ^ 0x7f; comptime var i = 30; inline while (i > 0) : (i -= 1) { @@ -412,7 +413,7 @@ pub const Fe = struct { } /// Compute the square root of `x2`, returning `error.NotSquare` if `x2` was not a square - pub fn sqrt(x2: Fe) !Fe { + pub fn sqrt(x2: Fe) Error!Fe { var x2_copy = x2; const x = x2.uncheckedSqrt(); const check = x.sq().sub(x2_copy); diff --git a/lib/std/crypto/25519/ristretto255.zig b/lib/std/crypto/25519/ristretto255.zig index 46bb9697e2..4644b7622e 100644 --- a/lib/std/crypto/25519/ristretto255.zig +++ b/lib/std/crypto/25519/ristretto255.zig @@ -5,6 +5,7 @@ // and substantial portions of the software. const std = @import("std"); const fmt = std.fmt; +const Error = std.crypto.Error; /// Group operations over Edwards25519. pub const Ristretto255 = struct { @@ -34,7 +35,7 @@ pub const Ristretto255 = struct { return .{ .ratio_is_square = @boolToInt(has_m_root) | @boolToInt(has_p_root), .root = x.abs() }; } - fn rejectNonCanonical(s: [encoded_length]u8) !void { + fn rejectNonCanonical(s: [encoded_length]u8) Error!void { if ((s[0] & 1) != 0) { return error.NonCanonical; } @@ -42,7 +43,7 @@ pub const Ristretto255 = struct { } /// Reject the neutral element. - pub fn rejectIdentity(p: Ristretto255) callconv(.Inline) !void { + pub fn rejectIdentity(p: Ristretto255) callconv(.Inline) Error!void { return p.p.rejectIdentity(); } @@ -50,7 +51,7 @@ pub const Ristretto255 = struct { pub const basePoint = Ristretto255{ .p = Curve.basePoint }; /// Decode a Ristretto255 representative. - pub fn fromBytes(s: [encoded_length]u8) !Ristretto255 { + pub fn fromBytes(s: [encoded_length]u8) Error!Ristretto255 { try rejectNonCanonical(s); const s_ = Fe.fromBytes(s); const ss = s_.sq(); // s^2 @@ -153,7 +154,7 @@ pub const Ristretto255 = struct { /// Multiply a Ristretto255 element with a scalar. /// Return error.WeakPublicKey if the resulting element is /// the identity element. - pub fn mul(p: Ristretto255, s: [encoded_length]u8) callconv(.Inline) !Ristretto255 { + pub fn mul(p: Ristretto255, s: [encoded_length]u8) callconv(.Inline) Error!Ristretto255 { return Ristretto255{ .p = try p.p.mul(s) }; } diff --git a/lib/std/crypto/25519/scalar.zig b/lib/std/crypto/25519/scalar.zig index e4fb277807..a4bf5aafcf 100644 --- a/lib/std/crypto/25519/scalar.zig +++ b/lib/std/crypto/25519/scalar.zig @@ -5,6 +5,7 @@ // and substantial portions of the software. const std = @import("std"); const mem = std.mem; +const Error = std.crypto.Error; /// 2^252 + 27742317777372353535851937790883648493 pub const field_size = [32]u8{ @@ -18,7 +19,7 @@ pub const CompressedScalar = [32]u8; pub const zero = [_]u8{0} ** 32; /// Reject a scalar whose encoding is not canonical. -pub fn rejectNonCanonical(s: [32]u8) !void { +pub fn rejectNonCanonical(s: [32]u8) Error!void { var c: u8 = 0; var n: u8 = 1; var i: usize = 31; diff --git a/lib/std/crypto/25519/x25519.zig b/lib/std/crypto/25519/x25519.zig index 5d0479bd4d..2d53124056 100644 --- a/lib/std/crypto/25519/x25519.zig +++ b/lib/std/crypto/25519/x25519.zig @@ -9,6 +9,7 @@ const mem = std.mem; const fmt = std.fmt; const Sha512 = crypto.hash.sha2.Sha512; +const Error = crypto.Error; /// X25519 DH function. pub const X25519 = struct { @@ -31,7 +32,7 @@ pub const X25519 = struct { secret_key: [secret_length]u8, /// Create a new key pair using an optional seed. - pub fn create(seed: ?[seed_length]u8) !KeyPair { + pub fn create(seed: ?[seed_length]u8) Error!KeyPair { const sk = seed orelse sk: { var random_seed: [seed_length]u8 = undefined; crypto.random.bytes(&random_seed); @@ -44,7 +45,7 @@ pub const X25519 = struct { } /// Create a key pair from an Ed25519 key pair - pub fn fromEd25519(ed25519_key_pair: crypto.sign.Ed25519.KeyPair) !KeyPair { + pub fn fromEd25519(ed25519_key_pair: crypto.sign.Ed25519.KeyPair) Error!KeyPair { const seed = ed25519_key_pair.secret_key[0..32]; var az: [Sha512.digest_length]u8 = undefined; Sha512.hash(seed, &az, .{}); @@ -59,13 +60,13 @@ pub const X25519 = struct { }; /// Compute the public key for a given private key. - pub fn recoverPublicKey(secret_key: [secret_length]u8) ![public_length]u8 { + pub fn recoverPublicKey(secret_key: [secret_length]u8) Error![public_length]u8 { const q = try Curve.basePoint.clampedMul(secret_key); return q.toBytes(); } /// Compute the X25519 equivalent to an Ed25519 public eky. - pub fn publicKeyFromEd25519(ed25519_public_key: [crypto.sign.Ed25519.public_length]u8) ![public_length]u8 { + pub fn publicKeyFromEd25519(ed25519_public_key: [crypto.sign.Ed25519.public_length]u8) Error![public_length]u8 { const pk_ed = try crypto.ecc.Edwards25519.fromBytes(ed25519_public_key); const pk = try Curve.fromEdwards25519(pk_ed); return pk.toBytes(); @@ -74,7 +75,7 @@ pub const X25519 = struct { /// Compute the scalar product of a public key and a secret scalar. /// Note that the output should not be used as a shared secret without /// hashing it first. - pub fn scalarmult(secret_key: [secret_length]u8, public_key: [public_length]u8) ![shared_length]u8 { + pub fn scalarmult(secret_key: [secret_length]u8, public_key: [public_length]u8) Error![shared_length]u8 { const q = try Curve.fromBytes(public_key).clampedMul(secret_key); return q.toBytes(); } diff --git a/lib/std/crypto/aegis.zig b/lib/std/crypto/aegis.zig index 2983f68ce8..3969d59e10 100644 --- a/lib/std/crypto/aegis.zig +++ b/lib/std/crypto/aegis.zig @@ -8,6 +8,7 @@ const std = @import("std"); const mem = std.mem; const assert = std.debug.assert; const AesBlock = std.crypto.core.aes.Block; +const Error = std.crypto.Error; const State128L = struct { blocks: [8]AesBlock, @@ -136,7 +137,7 @@ pub const Aegis128L = struct { /// ad: Associated Data /// npub: public nonce /// k: private key - pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) !void { + 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 { assert(c.len == m.len); var state = State128L.init(key, npub); var src: [32]u8 align(16) = undefined; @@ -298,7 +299,7 @@ pub const Aegis256 = struct { /// ad: Associated Data /// npub: public nonce /// k: private key - pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) !void { + 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 { assert(c.len == m.len); var state = State256.init(key, npub); var src: [16]u8 align(16) = undefined; diff --git a/lib/std/crypto/aes_gcm.zig b/lib/std/crypto/aes_gcm.zig index 5ef3f93963..bcb1b4c5fa 100644 --- a/lib/std/crypto/aes_gcm.zig +++ b/lib/std/crypto/aes_gcm.zig @@ -12,6 +12,7 @@ const debug = std.debug; const Ghash = std.crypto.onetimeauth.Ghash; const mem = std.mem; const modes = crypto.core.modes; +const Error = crypto.Error; pub const Aes128Gcm = AesGcm(crypto.core.aes.Aes128); pub const Aes256Gcm = AesGcm(crypto.core.aes.Aes256); @@ -59,7 +60,7 @@ fn AesGcm(comptime Aes: anytype) type { } } - pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) !void { + 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 { assert(c.len == m.len); const aes = Aes.initEnc(key); diff --git a/lib/std/crypto/aes_ocb.zig b/lib/std/crypto/aes_ocb.zig index ab0138f181..9eb0561d9f 100644 --- a/lib/std/crypto/aes_ocb.zig +++ b/lib/std/crypto/aes_ocb.zig @@ -10,6 +10,7 @@ const aes = crypto.core.aes; const assert = std.debug.assert; const math = std.math; const mem = std.mem; +const Error = crypto.Error; pub const Aes128Ocb = AesOcb(aes.Aes128); pub const Aes256Ocb = AesOcb(aes.Aes256); @@ -178,7 +179,7 @@ fn AesOcb(comptime Aes: anytype) type { /// ad: Associated Data /// npub: public nonce /// k: secret key - pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) !void { + 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 { assert(c.len == m.len); const aes_enc_ctx = Aes.initEnc(key); diff --git a/lib/std/crypto/bcrypt.zig b/lib/std/crypto/bcrypt.zig index caceb6d7b9..d00108b9c4 100644 --- a/lib/std/crypto/bcrypt.zig +++ b/lib/std/crypto/bcrypt.zig @@ -11,7 +11,8 @@ const math = std.math; const mem = std.mem; const debug = std.debug; const testing = std.testing; -const utils = std.crypto.utils; +const utils = crypto.utils; +const Error = crypto.Error; const salt_length: usize = 16; const salt_str_length: usize = 22; @@ -21,13 +22,6 @@ const ct_length: usize = 24; /// Length (in bytes) of a password hash pub const hash_length: usize = 60; -pub const BcryptError = error{ - /// The hashed password cannot be decoded. - InvalidEncoding, - /// The hash is not valid for the given password. - InvalidPassword, -}; - const State = struct { sboxes: [4][256]u32 = [4][256]u32{ .{ 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 { debug.assert(j == b64.len); } - fn decode(bin: []u8, b64: []const u8) BcryptError!void { + fn decode(bin: []u8, b64: []const u8) Error!void { var i: usize = 0; var j: usize = 0; while (j < bin.len) { @@ -210,7 +204,7 @@ const Codec = struct { } }; -fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) BcryptError![hash_length]u8 { +fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) Error![hash_length]u8 { var state = State{}; var password_buf: [73]u8 = undefined; 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) /// IMPORTANT: by design, bcrypt silently truncates passwords to 72 bytes. /// If this is an issue for your application, hash the password first using a function such as SHA-512, /// and then use the resulting hash as the password parameter for bcrypt. -pub fn strHash(password: []const u8, rounds_log: u6) ![hash_length]u8 { +pub fn strHash(password: []const u8, rounds_log: u6) Error![hash_length]u8 { var salt: [salt_length]u8 = undefined; crypto.random.bytes(&salt); return strHashInternal(password, rounds_log, salt); } /// Verify that a previously computed hash is valid for a given password. -pub fn strVerify(h: [hash_length]u8, password: []const u8) BcryptError!void { +pub fn strVerify(h: [hash_length]u8, password: []const u8) Error!void { if (!mem.eql(u8, "$2", h[0..2])) return error.InvalidEncoding; if (h[3] != '$' or h[6] != '$') return error.InvalidEncoding; const rounds_log_str = h[4..][0..2]; @@ -275,7 +269,7 @@ pub fn strVerify(h: [hash_length]u8, password: []const u8) BcryptError!void { const rounds_log = fmt.parseInt(u6, rounds_log_str[0..], 10) catch return error.InvalidEncoding; const wanted_s = try strHashInternal(password, rounds_log, salt); if (!mem.eql(u8, wanted_s[0..], h[0..])) { - return error.InvalidPassword; + return error.PasswordVerificationFailed; } } @@ -292,7 +286,7 @@ test "bcrypt codec" { test "bcrypt" { const s = try strHash("password", 5); try strVerify(s, "password"); - testing.expectError(error.InvalidPassword, strVerify(s, "invalid password")); + testing.expectError(error.PasswordVerificationFailed, strVerify(s, "invalid password")); const long_s = try strHash("password" ** 100, 5); try strVerify(long_s, "password" ** 100); diff --git a/lib/std/crypto/chacha20.zig b/lib/std/crypto/chacha20.zig index e01888e793..4611923892 100644 --- a/lib/std/crypto/chacha20.zig +++ b/lib/std/crypto/chacha20.zig @@ -13,6 +13,7 @@ const testing = std.testing; const maxInt = math.maxInt; const Vector = std.meta.Vector; const Poly1305 = std.crypto.onetimeauth.Poly1305; +const Error = std.crypto.Error; // Vectorized implementation of the core function const ChaCha20VecImpl = struct { @@ -656,7 +657,7 @@ fn chacha20poly1305Seal(ciphertextAndTag: []u8, plaintext: []const u8, data: []c } /// Verifies and decrypts an authenticated message produced by chacha20poly1305SealDetached. -fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_length]u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void { +fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_length]u8, data: []const u8, key: [32]u8, nonce: [12]u8) Error!void { // split ciphertext and tag assert(dst.len == ciphertext.len); @@ -702,9 +703,9 @@ fn chacha20poly1305OpenDetached(dst: []u8, ciphertext: []const u8, tag: *const [ } /// Verifies and decrypts an authenticated message produced by chacha20poly1305Seal. -fn chacha20poly1305Open(dst: []u8, ciphertextAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void { +fn chacha20poly1305Open(dst: []u8, ciphertextAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) Error!void { if (ciphertextAndTag.len < chacha20poly1305_tag_length) { - return error.InvalidMessage; + return error.AuthenticationFailed; } const ciphertextLen = ciphertextAndTag.len - chacha20poly1305_tag_length; 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: [] } /// Verifies and decrypts an authenticated message produced by xchacha20poly1305SealDetached. -fn xchacha20poly1305OpenDetached(plaintext: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_length]u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void { +fn xchacha20poly1305OpenDetached(plaintext: []u8, ciphertext: []const u8, tag: *const [chacha20poly1305_tag_length]u8, data: []const u8, key: [32]u8, nonce: [24]u8) Error!void { const extended = extend(key, nonce); return try chacha20poly1305OpenDetached(plaintext, ciphertext, tag, data, extended.key, extended.nonce); } /// Verifies and decrypts an authenticated message produced by xchacha20poly1305Seal. -fn xchacha20poly1305Open(ciphertextAndTag: []u8, msgAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) !void { +fn xchacha20poly1305Open(ciphertextAndTag: []u8, msgAndTag: []const u8, data: []const u8, key: [32]u8, nonce: [24]u8) Error!void { const extended = extend(key, nonce); return try chacha20poly1305Open(ciphertextAndTag, msgAndTag, data, extended.key, extended.nonce); } @@ -864,7 +865,7 @@ test "open" { testing.expectError(error.AuthenticationFailed, chacha20poly1305Open(out[0..], ciphertext[0..], data[0..], key, bad_nonce)); // a short ciphertext should result in a different error - testing.expectError(error.InvalidMessage, chacha20poly1305Open(out[0..], "", data[0..], key, bad_nonce)); + testing.expectError(error.AuthenticationFailed, chacha20poly1305Open(out[0..], "", data[0..], key, bad_nonce)); } } @@ -915,7 +916,7 @@ pub const Chacha20Poly1305 = struct { /// npub: public nonce /// k: private key /// NOTE: the check of the authentication tag is currently not done in constant time - pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) !void { + 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 { assert(c.len == m.len); return try chacha20poly1305OpenDetached(m, c, tag[0..], ad, k, npub); } @@ -944,7 +945,7 @@ pub const XChacha20Poly1305 = struct { /// npub: public nonce /// k: private key /// NOTE: the check of the authentication tag is currently not done in constant time - pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) !void { + 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 { assert(c.len == m.len); return try xchacha20poly1305OpenDetached(m, c, tag[0..], ad, k, npub); } diff --git a/lib/std/crypto/error.zig b/lib/std/crypto/error.zig new file mode 100644 index 0000000000..4cb12bb8f7 --- /dev/null +++ b/lib/std/crypto/error.zig @@ -0,0 +1,34 @@ +pub const Error = error{ + /// MAC verification failed - The tag doesn't verify for the given ciphertext and secret key + AuthenticationFailed, + + /// The requested output length is too long for the chosen algorithm + OutputTooLong, + + /// Finite field operation returned the identity element + IdentityElement, + + /// Encoded input cannot be decoded + InvalidEncoding, + + /// The signature does't verify for the given message and public key + SignatureVerificationFailed, + + /// Both a public and secret key have been provided, but they are incompatible + KeyMismatch, + + /// Encoded input is not in canonical form + NonCanonical, + + /// Square root has no solutions + NotSquare, + + /// Verification string doesn't match the provided password and parameters + PasswordVerificationFailed, + + /// Parameters would be insecure to use + WeakParameters, + + /// Public key would be insecure to use + WeakPublicKey, +}; diff --git a/lib/std/crypto/gimli.zig b/lib/std/crypto/gimli.zig index 1c1d6c79db..111e0c5274 100644 --- a/lib/std/crypto/gimli.zig +++ b/lib/std/crypto/gimli.zig @@ -20,6 +20,7 @@ const assert = std.debug.assert; const testing = std.testing; const htest = @import("test.zig"); const Vector = std.meta.Vector; +const Error = std.crypto.Error; pub const State = struct { pub const BLOCKBYTES = 48; @@ -392,7 +393,7 @@ pub const Aead = struct { /// npub: public nonce /// k: private key /// NOTE: the check of the authentication tag is currently not done in constant time - pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) !void { + 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 { assert(c.len == m.len); var state = Aead.init(ad, npub, k); @@ -429,7 +430,7 @@ pub const Aead = struct { // TODO: use a constant-time equality check here, see https://github.com/ziglang/zig/issues/1776 if (!mem.eql(u8, buf[0..State.RATE], &tag)) { @memset(m.ptr, undefined, m.len); - return error.InvalidMessage; + return error.AuthenticationFailed; } } }; diff --git a/lib/std/crypto/isap.zig b/lib/std/crypto/isap.zig index 990a0e7450..5219742d85 100644 --- a/lib/std/crypto/isap.zig +++ b/lib/std/crypto/isap.zig @@ -3,6 +3,7 @@ const debug = std.debug; const mem = std.mem; const math = std.math; const testing = std.testing; +const Error = std.crypto.Error; /// ISAPv2 is an authenticated encryption system hardened against side channels and fault attacks. /// 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 { tag.* = mac(c, ad, npub, key); } - pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) !void { + 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 { var computed_tag = mac(c, ad, npub, key); var acc: u8 = 0; for (computed_tag) |_, j| { diff --git a/lib/std/crypto/pbkdf2.zig b/lib/std/crypto/pbkdf2.zig index 25df1ba440..ce1912091b 100644 --- a/lib/std/crypto/pbkdf2.zig +++ b/lib/std/crypto/pbkdf2.zig @@ -7,6 +7,7 @@ const std = @import("std"); const mem = std.mem; const maxInt = std.math.maxInt; +const Error = std.crypto.Error; // RFC 2898 Section 5.2 // @@ -36,14 +37,6 @@ const maxInt = std.math.maxInt; // Based on Apple's CommonKeyDerivation, based originally on code by Damien Bergamini. -pub const Pbkdf2Error = error{ - /// At least one round is required - TooFewRounds, - - /// Maximum length of the derived key is `maxInt(u32) * Prf.mac_length` - DerivedKeyTooLong, -}; - /// Apply PBKDF2 to generate a key from a password. /// /// PBKDF2 is defined in RFC 2898, and is a recommendation of NIST SP 800-132. @@ -62,8 +55,8 @@ pub const Pbkdf2Error = error{ /// the derivedKey. It is common to tune this parameter to achieve approximately 100ms. /// /// Prf: Pseudo-random function to use. A common choice is `std.crypto.auth.hmac.HmacSha256`. -pub fn pbkdf2(derivedKey: []u8, password: []const u8, salt: []const u8, rounds: u32, comptime Prf: type) Pbkdf2Error!void { - if (rounds < 1) return error.TooFewRounds; +pub fn pbkdf2(derivedKey: []u8, password: []const u8, salt: []const u8, rounds: u32, comptime Prf: type) Error!void { + if (rounds < 1) return error.WeakParameters; const dkLen = derivedKey.len; const hLen = Prf.mac_length; @@ -76,7 +69,7 @@ pub fn pbkdf2(derivedKey: []u8, password: []const u8, salt: []const u8, rounds: // if (comptime (maxInt(usize) > maxInt(u32) * hLen) and (dkLen > @as(usize, maxInt(u32) * hLen))) { // If maxInt(usize) is less than `maxInt(u32) * hLen` then dkLen is always inbounds - return error.DerivedKeyTooLong; + return error.OutputTooLong; } // FromSpec: diff --git a/lib/std/crypto/salsa20.zig b/lib/std/crypto/salsa20.zig index e22668f998..006767c93f 100644 --- a/lib/std/crypto/salsa20.zig +++ b/lib/std/crypto/salsa20.zig @@ -15,6 +15,7 @@ const Vector = std.meta.Vector; const Poly1305 = crypto.onetimeauth.Poly1305; const Blake2b = crypto.hash.blake2.Blake2b; const X25519 = crypto.dh.X25519; +const Error = crypto.Error; const Salsa20VecImpl = struct { const Lane = Vector(4, u32); @@ -398,7 +399,7 @@ pub const XSalsa20Poly1305 = struct { /// ad: Associated Data /// npub: public nonce /// k: private key - pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) !void { + 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 { debug.assert(c.len == m.len); const extended = extend(k, npub); var block0 = [_]u8{0} ** 64; @@ -446,7 +447,7 @@ pub const SecretBox = struct { /// Verify and decrypt `c` using a nonce `npub` and a key `k`. /// `m` must be exactly `tag_length` smaller than `c`, as `c` includes an authentication tag in addition to the encrypted message. - pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, k: [key_length]u8) !void { + pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void { if (c.len < tag_length) { return error.AuthenticationFailed; } @@ -481,20 +482,20 @@ pub const Box = struct { pub const KeyPair = X25519.KeyPair; /// Compute a secret suitable for `secretbox` given a recipent's public key and a sender's secret key. - pub fn createSharedSecret(public_key: [public_length]u8, secret_key: [secret_length]u8) ![shared_length]u8 { + pub fn createSharedSecret(public_key: [public_length]u8, secret_key: [secret_length]u8) Error![shared_length]u8 { const p = try X25519.scalarmult(secret_key, public_key); const zero = [_]u8{0} ** 16; return Salsa20Impl.hsalsa20(zero, p); } /// Encrypt and authenticate a message using a recipient's public key `public_key` and a sender's `secret_key`. - pub fn seal(c: []u8, m: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) !void { + pub fn seal(c: []u8, m: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) Error!void { const shared_key = try createSharedSecret(public_key, secret_key); return SecretBox.seal(c, m, npub, shared_key); } /// Verify and decrypt a message using a recipient's secret key `public_key` and a sender's `public_key`. - pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) !void { + pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) Error!void { const shared_key = try createSharedSecret(public_key, secret_key); return SecretBox.open(m, c, npub, shared_key); } @@ -527,7 +528,7 @@ pub const SealedBox = struct { /// Encrypt a message `m` for a recipient whose public key is `public_key`. /// `c` must be `seal_length` bytes larger than `m`, so that the required metadata can be added. - pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) !void { + pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) Error!void { debug.assert(c.len == m.len + seal_length); var ekp = try KeyPair.create(null); const nonce = createNonce(ekp.public_key, public_key); @@ -538,7 +539,7 @@ pub const SealedBox = struct { /// Decrypt a message using a key pair. /// `m` must be exactly `seal_length` bytes smaller than `c`, as `c` also includes metadata. - pub fn open(m: []u8, c: []const u8, keypair: KeyPair) !void { + pub fn open(m: []u8, c: []const u8, keypair: KeyPair) Error!void { if (c.len < seal_length) { return error.AuthenticationFailed; } |
