1/* 2 * Argon2 reference source code package - reference C implementations 3 * 4 * Copyright 2015 5 * Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves 6 * 7 * You may use this work under the terms of a Creative Commons CC0 1.0 8 * License/Waiver or the Apache Public License 2.0, at your option. The terms of 9 * these licenses can be found at: 10 * 11 * - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 12 * - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * You should have received a copy of both of these licenses along with this 15 * software. If not, they may be obtained at the above URLs. 16 */ 17 18#include <stdio.h> 19#include <stdint.h> 20#include <stdlib.h> 21#include <string.h> 22#include <time.h> 23#include <assert.h> 24 25#include "argon2.h" 26 27#define OUT_LEN 32 28#define ENCODED_LEN 108 29 30/* Test harness will assert: 31 * argon2_hash() returns ARGON2_OK 32 * HEX output matches expected 33 * encoded output matches expected 34 * argon2_verify() correctly verifies value 35 */ 36 37void hashtest(uint32_t version, uint32_t t, uint32_t m, uint32_t p, char *pwd, 38 char *salt, char *hexref, char *mcfref, argon2_type type) { 39 unsigned char out[OUT_LEN]; 40 unsigned char hex_out[OUT_LEN * 2 + 4]; 41 char encoded[ENCODED_LEN]; 42 int ret, i; 43 44 printf("Hash test: $v=%d t=%d, m=%d, p=%d, pass=%s, salt=%s: ", version, 45 t, m, p, pwd, salt); 46 47 ret = argon2_hash(t, 1 << m, p, pwd, strlen(pwd), salt, strlen(salt), out, 48 OUT_LEN, encoded, ENCODED_LEN, type, version); 49 assert(ret == ARGON2_OK); 50 51 for (i = 0; i < OUT_LEN; ++i) 52 sprintf((char *)(hex_out + i * 2), "%02x", out[i]); 53 assert(memcmp(hex_out, hexref, OUT_LEN * 2) == 0); 54 55 if (ARGON2_VERSION_NUMBER == version) { 56 assert(memcmp(encoded, mcfref, strlen(mcfref)) == 0); 57 } 58 59 ret = argon2_verify(encoded, pwd, strlen(pwd), type); 60 assert(ret == ARGON2_OK); 61 ret = argon2_verify(mcfref, pwd, strlen(pwd), type); 62 assert(ret == ARGON2_OK); 63 64 printf("PASS\n"); 65} 66 67int main() { 68 int ret; 69 unsigned char out[OUT_LEN]; 70 char const *msg; 71 int version; 72 73 version = ARGON2_VERSION_10; 74 printf("Test Argon2i version number: %02x\n", version); 75 76 /* Multiple test cases for various input values */ 77 hashtest(version, 2, 16, 1, "password", "somesalt", 78 "f6c4db4a54e2a370627aff3db6176b94a2a209a62c8e36152711802f7b30c694", 79 "$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ" 80 "$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ", Argon2_i); 81#ifdef TEST_LARGE_RAM 82 hashtest(version, 2, 20, 1, "password", "somesalt", 83 "9690ec55d28d3ed32562f2e73ea62b02b018757643a2ae6e79528459de8106e9", 84 "$argon2i$m=1048576,t=2,p=1$c29tZXNhbHQ" 85 "$lpDsVdKNPtMlYvLnPqYrArAYdXZDoq5ueVKEWd6BBuk", Argon2_i); 86#endif 87 hashtest(version, 2, 18, 1, "password", "somesalt", 88 "3e689aaa3d28a77cf2bc72a51ac53166761751182f1ee292e3f677a7da4c2467", 89 "$argon2i$m=262144,t=2,p=1$c29tZXNhbHQ" 90 "$Pmiaqj0op3zyvHKlGsUxZnYXURgvHuKS4/Z3p9pMJGc", Argon2_i); 91 hashtest(version, 2, 8, 1, "password", "somesalt", 92 "fd4dd83d762c49bdeaf57c47bdcd0c2f1babf863fdeb490df63ede9975fccf06", 93 "$argon2i$m=256,t=2,p=1$c29tZXNhbHQ" 94 "$/U3YPXYsSb3q9XxHvc0MLxur+GP960kN9j7emXX8zwY", Argon2_i); 95 hashtest(version, 2, 8, 2, "password", "somesalt", 96 "b6c11560a6a9d61eac706b79a2f97d68b4463aa3ad87e00c07e2b01e90c564fb", 97 "$argon2i$m=256,t=2,p=2$c29tZXNhbHQ" 98 "$tsEVYKap1h6scGt5ovl9aLRGOqOth+AMB+KwHpDFZPs", Argon2_i); 99 hashtest(version, 1, 16, 1, "password", "somesalt", 100 "81630552b8f3b1f48cdb1992c4c678643d490b2b5eb4ff6c4b3438b5621724b2", 101 "$argon2i$m=65536,t=1,p=1$c29tZXNhbHQ" 102 "$gWMFUrjzsfSM2xmSxMZ4ZD1JCytetP9sSzQ4tWIXJLI", Argon2_i); 103 hashtest(version, 4, 16, 1, "password", "somesalt", 104 "f212f01615e6eb5d74734dc3ef40ade2d51d052468d8c69440a3a1f2c1c2847b", 105 "$argon2i$m=65536,t=4,p=1$c29tZXNhbHQ" 106 "$8hLwFhXm6110c03D70Ct4tUdBSRo2MaUQKOh8sHChHs", Argon2_i); 107 hashtest(version, 2, 16, 1, "differentpassword", "somesalt", 108 "e9c902074b6754531a3a0be519e5baf404b30ce69b3f01ac3bf21229960109a3", 109 "$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ" 110 "$6ckCB0tnVFMaOgvlGeW69ASzDOabPwGsO/ISKZYBCaM", Argon2_i); 111 hashtest(version, 2, 16, 1, "password", "diffsalt", 112 "79a103b90fe8aef8570cb31fc8b22259778916f8336b7bdac3892569d4f1c497", 113 "$argon2i$m=65536,t=2,p=1$ZGlmZnNhbHQ" 114 "$eaEDuQ/orvhXDLMfyLIiWXeJFvgza3vaw4kladTxxJc", Argon2_i); 115 116 /* Error state tests */ 117 118 /* Handle an invalid encoding correctly (it is missing a $) */ 119 ret = argon2_verify("$argon2i$m=65536,t=2,p=1c29tZXNhbHQ" 120 "$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ", 121 "password", strlen("password"), Argon2_i); 122 assert(ret == ARGON2_DECODING_FAIL); 123 printf("Recognise an invalid encoding: PASS\n"); 124 125 /* Handle an invalid encoding correctly (it is missing a $) */ 126 ret = argon2_verify("$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ" 127 "9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ", 128 "password", strlen("password"), Argon2_i); 129 assert(ret == ARGON2_DECODING_FAIL); 130 printf("Recognise an invalid encoding: PASS\n"); 131 132 /* Handle an invalid encoding correctly (salt is too short) */ 133 ret = argon2_verify("$argon2i$m=65536,t=2,p=1$" 134 "$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ", 135 "password", strlen("password"), Argon2_i); 136 assert(ret == ARGON2_SALT_TOO_SHORT); 137 printf("Recognise an invalid salt in encoding: PASS\n"); 138 139 /* Handle an mismatching hash (the encoded password is "passwore") */ 140 ret = argon2_verify("$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ" 141 "$b2G3seW+uPzerwQQC+/E1K50CLLO7YXy0JRcaTuswRo", 142 "password", strlen("password"), Argon2_i); 143 assert(ret == ARGON2_VERIFY_MISMATCH); 144 printf("Verify with mismatched password: PASS\n"); 145 146 msg = argon2_error_message(ARGON2_DECODING_FAIL); 147 assert(strcmp(msg, "Decoding failed") == 0); 148 printf("Decode an error message: PASS\n"); 149 150 printf("\n"); 151 152 version = ARGON2_VERSION_NUMBER; 153 printf("Test Argon2i version number: %02x\n", version); 154 155 /* Multiple test cases for various input values */ 156 hashtest(version, 2, 16, 1, "password", "somesalt", 157 "c1628832147d9720c5bd1cfd61367078729f6dfb6f8fea9ff98158e0d7816ed0", 158 "$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ" 159 "$wWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA", Argon2_i); 160#ifdef TEST_LARGE_RAM 161 hashtest(version, 2, 20, 1, "password", "somesalt", 162 "d1587aca0922c3b5d6a83edab31bee3c4ebaef342ed6127a55d19b2351ad1f41", 163 "$argon2i$v=19$m=1048576,t=2,p=1$c29tZXNhbHQ" 164 "$0Vh6ygkiw7XWqD7asxvuPE667zQu1hJ6VdGbI1GtH0E", Argon2_i); 165#endif 166 hashtest(version, 2, 18, 1, "password", "somesalt", 167 "296dbae80b807cdceaad44ae741b506f14db0959267b183b118f9b24229bc7cb", 168 "$argon2i$v=19$m=262144,t=2,p=1$c29tZXNhbHQ" 169 "$KW266AuAfNzqrUSudBtQbxTbCVkmexg7EY+bJCKbx8s", Argon2_i); 170 hashtest(version, 2, 8, 1, "password", "somesalt", 171 "89e9029f4637b295beb027056a7336c414fadd43f6b208645281cb214a56452f", 172 "$argon2i$v=19$m=256,t=2,p=1$c29tZXNhbHQ" 173 "$iekCn0Y3spW+sCcFanM2xBT63UP2sghkUoHLIUpWRS8", Argon2_i); 174 hashtest(version, 2, 8, 2, "password", "somesalt", 175 "4ff5ce2769a1d7f4c8a491df09d41a9fbe90e5eb02155a13e4c01e20cd4eab61", 176 "$argon2i$v=19$m=256,t=2,p=2$c29tZXNhbHQ" 177 "$T/XOJ2mh1/TIpJHfCdQan76Q5esCFVoT5MAeIM1Oq2E", Argon2_i); 178 hashtest(version, 1, 16, 1, "password", "somesalt", 179 "d168075c4d985e13ebeae560cf8b94c3b5d8a16c51916b6f4ac2da3ac11bbecf", 180 "$argon2i$v=19$m=65536,t=1,p=1$c29tZXNhbHQ" 181 "$0WgHXE2YXhPr6uVgz4uUw7XYoWxRkWtvSsLaOsEbvs8", Argon2_i); 182 hashtest(version, 4, 16, 1, "password", "somesalt", 183 "aaa953d58af3706ce3df1aefd4a64a84e31d7f54175231f1285259f88174ce5b", 184 "$argon2i$v=19$m=65536,t=4,p=1$c29tZXNhbHQ" 185 "$qqlT1YrzcGzj3xrv1KZKhOMdf1QXUjHxKFJZ+IF0zls", Argon2_i); 186 hashtest(version, 2, 16, 1, "differentpassword", "somesalt", 187 "14ae8da01afea8700c2358dcef7c5358d9021282bd88663a4562f59fb74d22ee", 188 "$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ" 189 "$FK6NoBr+qHAMI1jc73xTWNkCEoK9iGY6RWL1n7dNIu4", Argon2_i); 190 hashtest(version, 2, 16, 1, "password", "diffsalt", 191 "b0357cccfbef91f3860b0dba447b2348cbefecadaf990abfe9cc40726c521271", 192 "$argon2i$v=19$m=65536,t=2,p=1$ZGlmZnNhbHQ" 193 "$sDV8zPvvkfOGCw26RHsjSMvv7K2vmQq/6cxAcmxSEnE", Argon2_i); 194 195 196 /* Error state tests */ 197 198 /* Handle an invalid encoding correctly (it is missing a $) */ 199 ret = argon2_verify("$argon2i$v=19$m=65536,t=2,p=1c29tZXNhbHQ" 200 "$wWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA", 201 "password", strlen("password"), Argon2_i); 202 assert(ret == ARGON2_DECODING_FAIL); 203 printf("Recognise an invalid encoding: PASS\n"); 204 205 /* Handle an invalid encoding correctly (it is missing a $) */ 206 ret = argon2_verify("$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ" 207 "wWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA", 208 "password", strlen("password"), Argon2_i); 209 assert(ret == ARGON2_DECODING_FAIL); 210 printf("Recognise an invalid encoding: PASS\n"); 211 212 /* Handle an invalid encoding correctly (salt is too short) */ 213 ret = argon2_verify("$argon2i$v=19$m=65536,t=2,p=1$" 214 "$9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ", 215 "password", strlen("password"), Argon2_i); 216 assert(ret == ARGON2_SALT_TOO_SHORT); 217 printf("Recognise an invalid salt in encoding: PASS\n"); 218 219 /* Handle an mismatching hash (the encoded password is "passwore") */ 220 ret = argon2_verify("$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ" 221 "$8iIuixkI73Js3G1uMbezQXD0b8LG4SXGsOwoQkdAQIM", 222 "password", strlen("password"), Argon2_i); 223 assert(ret == ARGON2_VERIFY_MISMATCH); 224 printf("Verify with mismatched password: PASS\n"); 225 226 msg = argon2_error_message(ARGON2_DECODING_FAIL); 227 assert(strcmp(msg, "Decoding failed") == 0); 228 printf("Decode an error message: PASS\n\n"); 229 230 printf("Test Argon2id version number: %02x\n", version); 231 232 /* Multiple test cases for various input values */ 233 hashtest(version, 2, 16, 1, "password", "somesalt", 234 "09316115d5cf24ed5a15a31a3ba326e5cf32edc24702987c02b6566f61913cf7", 235 "$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ" 236 "$CTFhFdXPJO1aFaMaO6Mm5c8y7cJHAph8ArZWb2GRPPc", Argon2_id); 237 hashtest(version, 2, 18, 1, "password", "somesalt", 238 "78fe1ec91fb3aa5657d72e710854e4c3d9b9198c742f9616c2f085bed95b2e8c", 239 "$argon2id$v=19$m=262144,t=2,p=1$c29tZXNhbHQ" 240 "$eP4eyR+zqlZX1y5xCFTkw9m5GYx0L5YWwvCFvtlbLow", Argon2_id); 241 hashtest(version, 2, 8, 1, "password", "somesalt", 242 "9dfeb910e80bad0311fee20f9c0e2b12c17987b4cac90c2ef54d5b3021c68bfe", 243 "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ" 244 "$nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4", Argon2_id); 245 hashtest(version, 2, 8, 2, "password", "somesalt", 246 "6d093c501fd5999645e0ea3bf620d7b8be7fd2db59c20d9fff9539da2bf57037", 247 "$argon2id$v=19$m=256,t=2,p=2$c29tZXNhbHQ" 248 "$bQk8UB/VmZZF4Oo79iDXuL5/0ttZwg2f/5U52iv1cDc", Argon2_id); 249 hashtest(version, 1, 16, 1, "password", "somesalt", 250 "f6a5adc1ba723dddef9b5ac1d464e180fcd9dffc9d1cbf76cca2fed795d9ca98", 251 "$argon2id$v=19$m=65536,t=1,p=1$c29tZXNhbHQ" 252 "$9qWtwbpyPd3vm1rB1GThgPzZ3/ydHL92zKL+15XZypg", Argon2_id); 253 hashtest(version, 4, 16, 1, "password", "somesalt", 254 "9025d48e68ef7395cca9079da4c4ec3affb3c8911fe4f86d1a2520856f63172c", 255 "$argon2id$v=19$m=65536,t=4,p=1$c29tZXNhbHQ" 256 "$kCXUjmjvc5XMqQedpMTsOv+zyJEf5PhtGiUghW9jFyw", Argon2_id); 257 hashtest(version, 2, 16, 1, "differentpassword", "somesalt", 258 "0b84d652cf6b0c4beaef0dfe278ba6a80df6696281d7e0d2891b817d8c458fde", 259 "$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ" 260 "$C4TWUs9rDEvq7w3+J4umqA32aWKB1+DSiRuBfYxFj94", Argon2_id); 261 hashtest(version, 2, 16, 1, "password", "diffsalt", 262 "bdf32b05ccc42eb15d58fd19b1f856b113da1e9a5874fdcc544308565aa8141c", 263 "$argon2id$v=19$m=65536,t=2,p=1$ZGlmZnNhbHQ" 264 "$vfMrBczELrFdWP0ZsfhWsRPaHppYdP3MVEMIVlqoFBw", Argon2_id); 265 266 /* Common error state tests */ 267 268 printf("\n"); 269 printf("Common error state tests\n"); 270 271 ret = argon2_hash(2, 1, 1, "password", strlen("password"), 272 "diffsalt", strlen("diffsalt"), 273 out, OUT_LEN, NULL, 0, Argon2_id, version); 274 assert(ret == ARGON2_MEMORY_TOO_LITTLE); 275 printf("Fail on invalid memory: PASS\n"); 276 277 ret = argon2_hash(2, 1 << 12, 1, NULL, strlen("password"), 278 "diffsalt", strlen("diffsalt"), 279 out, OUT_LEN, NULL, 0, Argon2_id, version); 280 assert(ret == ARGON2_PWD_PTR_MISMATCH); 281 printf("Fail on invalid null pointer: PASS\n"); 282 283 ret = argon2_hash(2, 1 << 12, 1, "password", strlen("password"), "s", 1, 284 out, OUT_LEN, NULL, 0, Argon2_id, version); 285 assert(ret == ARGON2_SALT_TOO_SHORT); 286 printf("Fail on salt too short: PASS\n"); 287 288 return 0; 289} 290