Skip to content

Add onetimeauth functions #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ PHP NEWS
- Sodium:
. Add support for AEGIS-128L and AEGIS-256 (jedisct1)
. Enable AES-GCM on aarch64 with the ARM crypto extensions (jedisct1)
. Add sodium_crypto_onetimeauth_* functions for one-time Poly1305
MAC generation and verification (Ayesh Karunaratne)

- Standard:
. Implement GH-12188 (Indication for the int size in phpinfo()). (timwolla)
Expand Down
8 changes: 8 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,12 @@ PHP 8.4 UPGRADE NOTES
that was introduced in libsodium 1.0.19.
. sodium_crypto_aead_aes256gcm_*() functions are now enabled on aarch64 CPUs
with the ARM cryptographic extensions.
. Added sodium_crypto_onetimeauth(), sodium_crypto_onetimeauth_keygen(), and
sodium_crypto_onetimeauth_verify() functions for one-time authentication
based on Poly1305 Message Authentication Code. These MACs are 16 bytes
long, and are generated using a 32 byte key. Due to its output size,
Poly1305 is recommended for online protocols, exchanging many small
messages, rather than for authenticating very large files.

- Standard:
. Added the http_get_last_response_headers() and
Expand Down Expand Up @@ -550,6 +556,8 @@ PHP 8.4 UPGRADE NOTES
. SODIUM_CRYPTO_AEAD_AEGIS256_NSECBYTES
. SODIUM_CRYPTO_AEAD_AEGIS256_NPUBBYTES
. SODIUM_CRYPTO_AEAD_AEGIS256_ABYTES
. SODIUM_CRYPTO_ONETIMEAUTH_BYTES
. SODIUM_CRYPTO_ONETIMEAUTH_KEYBYTES

- XML:
. Added XML_OPTION_PARSE_HUGE to allow large inputs in xml_parse and
Expand Down
73 changes: 73 additions & 0 deletions ext/sodium/libsodium.c
Original file line number Diff line number Diff line change
Expand Up @@ -2942,6 +2942,68 @@ PHP_FUNCTION(sodium_crypto_auth_verify)
RETURN_TRUE;
}

PHP_FUNCTION(sodium_crypto_onetimeauth)
{
zend_string *mac;
char *key;
char *msg;
size_t msg_len;
size_t key_len;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss",
&msg, &msg_len,
&key, &key_len) == FAILURE) {
sodium_remove_param_values_from_backtrace(EG(exception));
RETURN_THROWS();
}
if (key_len != crypto_onetimeauth_KEYBYTES) {
zend_argument_error(sodium_exception_ce, 2, "must be SODIUM_CRYPTO_ONETIMEAUTH_KEYBYTES bytes long");
RETURN_THROWS();
}
mac = zend_string_alloc(crypto_onetimeauth_BYTES, 0);
if (crypto_onetimeauth((unsigned char *) ZSTR_VAL(mac),
(const unsigned char *) msg, msg_len,
(const unsigned char *) key) != 0) {
zend_throw_exception(sodium_exception_ce, "internal error", 0);
RETURN_THROWS();
}
ZSTR_VAL(mac)[crypto_onetimeauth_BYTES] = 0;

RETURN_STR(mac);
}

PHP_FUNCTION(sodium_crypto_onetimeauth_verify)
{
char *mac;
char *key;
char *msg;
size_t mac_len;
size_t msg_len;
size_t key_len;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss",
&mac, &mac_len,
&msg, &msg_len,
&key, &key_len) == FAILURE) {
sodium_remove_param_values_from_backtrace(EG(exception));
RETURN_THROWS();
}
if (key_len != crypto_onetimeauth_KEYBYTES) {
zend_argument_error(sodium_exception_ce, 3, "must be SODIUM_CRYPTO_ONETIMEAUTH_KEYBYTES bytes long");
RETURN_THROWS();
}
if (mac_len != crypto_onetimeauth_BYTES) {
zend_argument_error(sodium_exception_ce, 1, "must be SODIUM_CRYPTO_ONETIMEAUTH_BYTES bytes long");
RETURN_THROWS();
}
if (crypto_onetimeauth_verify((const unsigned char *) mac,
(const unsigned char *) msg, msg_len,
(const unsigned char *) key) != 0) {
RETURN_FALSE;
}
RETURN_TRUE;
}

PHP_FUNCTION(sodium_crypto_sign_ed25519_sk_to_curve25519)
{
zend_string *ecdhkey;
Expand Down Expand Up @@ -3103,6 +3165,17 @@ PHP_FUNCTION(sodium_crypto_auth_keygen)
RETURN_STRINGL((const char *) key, sizeof key);
}

PHP_FUNCTION(sodium_crypto_onetimeauth_keygen)
{
unsigned char key[crypto_onetimeauth_KEYBYTES];

if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}
randombytes_buf(key, sizeof key);
RETURN_STRINGL((const char *) key, sizeof key);
}

PHP_FUNCTION(sodium_crypto_generichash_keygen)
{
unsigned char key[crypto_generichash_KEYBYTES];
Expand Down
16 changes: 16 additions & 0 deletions ext/sodium/libsodium.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,16 @@
* @cvalue crypto_auth_KEYBYTES
*/
const SODIUM_CRYPTO_AUTH_KEYBYTES = UNKNOWN;
/**
* @var int
* @cvalue crypto_onetimeauth_BYTES
*/
const SODIUM_CRYPTO_ONETIMEAUTH_BYTES = UNKNOWN;
/**
* @var int
* @cvalue crypto_onetimeauth_KEYBYTES
*/
const SODIUM_CRYPTO_ONETIMEAUTH_KEYBYTES = UNKNOWN;
/**
* @var int
* @cvalue crypto_box_SEALBYTES
Expand Down Expand Up @@ -595,6 +605,12 @@ function sodium_crypto_auth_keygen(): string {}

function sodium_crypto_auth_verify(string $mac, string $message, #[\SensitiveParameter] string $key): bool {}

function sodium_crypto_onetimeauth(string $message, #[\SensitiveParameter] string $key): string {}

function sodium_crypto_onetimeauth_keygen(): string {}

function sodium_crypto_onetimeauth_verify(string $mac, string $message, #[\SensitiveParameter] string $key): bool {}

function sodium_crypto_box(#[\SensitiveParameter] string $message, string $nonce, #[\SensitiveParameter] string $key_pair): string {}

function sodium_crypto_box_keypair(): string {}
Expand Down
20 changes: 19 additions & 1 deletion ext/sodium/libsodium_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 47 additions & 0 deletions ext/sodium/tests/crypto_onetimeauth.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
--TEST--
Tests for libsodium onetimeauth functionality
--EXTENSIONS--
sodium
--FILE--
<?php
$msg = random_bytes(1000);
$key = sodium_crypto_onetimeauth_keygen();
$mac = sodium_crypto_onetimeauth($msg, $key);

// This should validate
var_dump(sodium_crypto_onetimeauth_verify($mac, $msg, $key));

$bad_key = random_bytes(SODIUM_CRYPTO_ONETIMEAUTH_KEYBYTES - 1);
try {
$mac = sodium_crypto_onetimeauth($msg, $bad_key);
echo 'Fail!', PHP_EOL;
} catch (SodiumException $ex) {
echo $ex->getMessage(), PHP_EOL;
}

// Flip the first bit
$badmsg = $msg;
$badmsg[0] = \chr(\ord($badmsg[0]) ^ 0x80);
var_dump(sodium_crypto_onetimeauth_verify($mac, $badmsg, $key));

// Let's flip a bit pseudo-randomly
$badmsg = $msg;
$badmsg[$i=mt_rand(0, 999)] = \chr(
\ord($msg[$i]) ^ (
1 << mt_rand(0, 7)
)
);

var_dump(sodium_crypto_onetimeauth_verify($mac, $badmsg, $key));

// Now let's change a bit in the MAC
$badmac = $mac;
$badmac[0] = \chr(\ord($badmac[0]) ^ 0x80);
var_dump(sodium_crypto_onetimeauth_verify($badmac, $msg, $key));
?>
--EXPECT--
bool(true)
sodium_crypto_onetimeauth(): Argument #2 ($key) must be SODIUM_CRYPTO_ONETIMEAUTH_KEYBYTES bytes long
bool(false)
bool(false)
bool(false)