static inline bool authValid(Dict* message, uint8_t* buffer, uint32_t length, struct Admin* admin) { String* cookieStr = Dict_getString(message, String_CONST("cookie")); uint32_t cookie = (cookieStr != NULL) ? strtoll(cookieStr->bytes, NULL, 10) : 0; if (!cookie) { int64_t* cookieInt = Dict_getInt(message, String_CONST("cookie")); cookie = (cookieInt) ? *cookieInt : 0; } uint64_t nowSecs = Time_currentTimeSeconds(admin->eventBase); String* submittedHash = Dict_getString(message, String_CONST("hash")); if (cookie > nowSecs || cookie < nowSecs - 20 || !submittedHash || submittedHash->len != 64) { return false; } uint8_t* hashPtr = (uint8_t*) strstr((char*) buffer, submittedHash->bytes); if (!hashPtr || !admin->password) { return false; } uint8_t passAndCookie[64]; snprintf((char*) passAndCookie, 64, "%s%u", admin->password->bytes, cookie); uint8_t hash[32]; crypto_hash_sha256(hash, passAndCookie, strlen((char*) passAndCookie)); Hex_encode(hashPtr, 64, hash, 32); crypto_hash_sha256(hash, buffer, length); Hex_encode(hashPtr, 64, hash, 32); return memcmp(hashPtr, submittedHash->bytes, 64) == 0; }
static int calculateAuth(Dict* message, String* password, String* cookieStr, struct Allocator* alloc) { // Calculate the hash of the password. String* hashHex = String_newBinary(NULL, 64, alloc); uint8_t passAndCookie[64]; uint32_t cookie = (cookieStr != NULL) ? strtoll(cookieStr->bytes, NULL, 10) : 0; snprintf((char*) passAndCookie, 64, "%s%u", password->bytes, cookie); uint8_t hash[32]; crypto_hash_sha256(hash, passAndCookie, strlen((char*) passAndCookie)); Hex_encode((uint8_t*)hashHex->bytes, 64, hash, 32); Dict_putString(message, String_new("hash", alloc), hashHex, alloc); Dict_putString(message, String_new("cookie", alloc), cookieStr, alloc); // serialize the message with the password hash uint8_t buffer[AdminClient_MAX_MESSAGE_SIZE]; struct Writer* writer = ArrayWriter_new(buffer, AdminClient_MAX_MESSAGE_SIZE, alloc); if (StandardBencSerializer_get()->serializeDictionary(writer, message)) { return -1; } int length = writer->bytesWritten; // calculate the hash of the message with the password hash crypto_hash_sha256(hash, buffer, length); // swap the hash of the message with the password hash into the location // where the password hash was. Hex_encode((uint8_t*)hashHex->bytes, 64, hash, 32); return 0; }
static int calculateAuth(Dict* message, String* password, String* cookieStr, struct Allocator* alloc) { // Calculate the hash of the password. String* hashHex = String_newBinary(NULL, 64, alloc); uint8_t passAndCookie[64]; uint32_t cookie = (cookieStr != NULL) ? strtoll(cookieStr->bytes, NULL, 10) : 0; snprintf((char*) passAndCookie, 64, "%s%u", password->bytes, cookie); uint8_t hash[32]; crypto_hash_sha256(hash, passAndCookie, CString_strlen((char*) passAndCookie)); Hex_encode((uint8_t*)hashHex->bytes, 64, hash, 32); Dict_putString(message, String_new("hash", alloc), hashHex, alloc); Dict_putString(message, String_new("cookie", alloc), cookieStr, alloc); // serialize the message with the password hash struct Message* msg = Message_new(0, AdminClient_MAX_MESSAGE_SIZE, alloc); BencMessageWriter_write(message, msg, NULL); // calculate the hash of the message with the password hash crypto_hash_sha256(hash, msg->bytes, msg->length); // swap the hash of the message with the password hash into the location // where the password hash was. Hex_encode((uint8_t*)hashHex->bytes, 64, hash, 32); return 0; }
Auth::Auth(const char *passphrase) { this->passphrase = passphrase; //TODO evalute this for better keystreching crypto_hash_sha256(this->encryptionkey, (const unsigned char*)passphrase, this->passphrase.length()); for (int i=0;i<65535;++i) crypto_hash_sha256(this->encryptionkey, (const unsigned char*)this->encryptionkey, crypto_hash_sha256_BYTES); }
static inline void hashPassword_sha256(struct Auth* auth, const String* password) { uint8_t tempBuff[32]; crypto_hash_sha256(auth->secret, (uint8_t*) password->bytes, password->len); crypto_hash_sha256(tempBuff, auth->secret, 32); memcpy(auth->challenge.bytes, tempBuff, Headers_AuthChallenge_SIZE); Headers_setAuthChallengeDerivations(&auth->challenge, 0); auth->challenge.challenge.type = 1; }
static inline void getPasswordHash(uint8_t output[32], uint8_t derivations, struct Auth* auth) { uint8_t tempBuff[32]; memcpy(output, auth->secret, 32); for (uint32_t i = 0; i < derivations; i++) { crypto_hash_sha256(tempBuff, output, 32); crypto_hash_sha256(output, tempBuff, 32); } }
/* Same as above, except with use the given salt for deterministic key derivation. * The salt must be TOX_PASS_SALT_LENGTH bytes in length. */ bool tox_pass_key_derive_with_salt(Tox_Pass_Key *out_key, const uint8_t *passphrase, size_t pplength, const uint8_t *salt, TOX_ERR_KEY_DERIVATION *error) { if (!salt || !out_key || (!passphrase && pplength != 0)) { SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL); return 0; } uint8_t passkey[crypto_hash_sha256_BYTES]; crypto_hash_sha256(passkey, passphrase, pplength); uint8_t key[CRYPTO_SHARED_KEY_SIZE]; /* Derive a key from the password */ /* http://doc.libsodium.org/key_derivation/README.html */ /* note that, according to the documentation, a generic pwhash interface will be created * once the pwhash competition (https://password-hashing.net/) is over */ if (crypto_pwhash_scryptsalsa208sha256( key, sizeof(key), (char *)passkey, sizeof(passkey), salt, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { /* out of memory most likely */ SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_FAILED); return 0; } sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ memcpy(out_key->salt, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); memcpy(out_key->key, key, CRYPTO_SHARED_KEY_SIZE); SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_OK); return 1; }
/** * Get a shared secret. * * @param outputSecret an array to place the shared secret in. * @param myPrivateKey * @param herPublicKey * @param logger * @param passwordHash a 32 byte value known to both ends, this must be provably pseudorandom * the first 32 bytes of a sha256 output from hashing a password is ok, * whatever she happens to send me in the Auth field is NOT ok. * If this field is null, the secret will be generated without the password. */ static inline void getSharedSecret(uint8_t outputSecret[32], uint8_t myPrivateKey[32], uint8_t herPublicKey[32], uint8_t passwordHash[32], struct Log* logger) { uint8_t tempBuff[64]; crypto_scalarmult_curve25519(tempBuff, myPrivateKey, herPublicKey); if (passwordHash == NULL) { crypto_core_hsalsa20(outputSecret, keyHashNonce, tempBuff, keyHashSigma); } else { memcpy(&tempBuff[32], passwordHash, 32); crypto_hash_sha256(outputSecret, tempBuff, 64); } #ifdef Log_KEYS uint8_t myPublicKeyHex[65]; printHexPubKey(myPublicKeyHex, myPrivateKey); uint8_t herPublicKeyHex[65]; printHexKey(herPublicKeyHex, herPublicKey); uint8_t passwordHashHex[65]; printHexKey(passwordHashHex, passwordHash); uint8_t outputSecretHex[65] = "NULL"; printHexKey(outputSecretHex, outputSecret); Log_keys4(logger, "Generated a shared secret:\n" " myPublicKey=%s\n" " herPublicKey=%s\n" " passwordHash=%s\n" " outputSecret=%s\n", myPublicKeyHex, herPublicKeyHex, passwordHashHex, outputSecretHex); #endif }
int main(void) { int i; crypto_stream_aes256estream(output,4194304,nonce,firstkey); crypto_hash_sha256(h,output,sizeof output); for (i = 0;i < 32;++i) printf("%02x",h[i]); printf("\n"); return 0; }
int yacl_sha256 (const uint8_t *in, size_t len, uint8_t out[YACL_SHA256_LEN]) { #ifdef HAVE_LIBSODIUM return crypto_hash_sha256 (out, in, len); #else return sha256 (in, len, out); #endif }
main(int argc, char **argv) { if (argc<2) { write(2,USAGE,strlen(USAGE)); exit(64); } unsigned char cache[131072*32]={0}; struct passwd *urcd = getpwnam("urcd"); if ((!urcd) || (chdir(argv[1])) || (chroot(argv[1])) || (setgroups(0,'\x00')) || (setgid(urcd->pw_gid)) || (setuid(urcd->pw_uid))) exit(64); unsigned char buffer[16+8+65536+32]; unsigned char hash[32]; int i, n, l; while (1) { readbuffer: if (read(0,buffer,2)<2) exit(1); n = 0; l = 16 + 8 + buffer[0] * 256 + buffer[1]; while (n<l) { i = read(0,buffer+n,l-n); if (i<1) exit(2); n += i; } crypto_hash_sha256(hash,buffer,l); for (i=131072*32-32;i>-32;i-=32) if (!crypto_verify_32(hash,cache+i)) { if (write(1,"\1",1)<1) exit(3); goto readbuffer; } memcpy(cache,cache+32,131072*32-32); memcpy(cache+131072*32-32,hash,32); if (write(1,"\0",1)<1) exit(4); } }
static inline void hashPassword(uint8_t secretOut[32], union CryptoHeader_Challenge* challengeOut, const String* login, const String* password, const uint8_t authType) { crypto_hash_sha256(secretOut, (uint8_t*) password->bytes, password->len); uint8_t tempBuff[32]; if (authType == 1) { crypto_hash_sha256(tempBuff, secretOut, 32); } else if (authType == 2) { crypto_hash_sha256(tempBuff, (uint8_t*) login->bytes, login->len); } else { Assert_failure("Unsupported auth type [%u]", authType); } Bits_memcpyConst(challengeOut->bytes, tempBuff, CryptoHeader_Challenge_SIZE); CryptoHeader_setAuthChallengeDerivations(challengeOut, 0); challengeOut->challenge.type = authType; challengeOut->challenge.additional = 0; }
PyObject *pycrypto_hash_sha256(PyObject *self, PyObject *args, PyObject *kw){ char *m; Py_ssize_t msize=0; unsigned char h[crypto_hash_sha256_BYTES]; static const char *kwlist[] = {"m",0}; if (!PyArg_ParseTupleAndKeywords(args, kw, "|s#:crypto_hash_sha256", (char **)kwlist, &m, &msize)){ return (PyObject *)0;} crypto_hash_sha256(h, (const unsigned char *)m, msize); return PyBytes_FromStringAndSize((char *)h, crypto_hash_sha256_BYTES);}
Auth::Response Auth::getResponse(const Challenge &challenge) const { Response response; int inputlen = passphrase.length() + challenge.size(); unsigned char input[inputlen]; memcpy(input, passphrase.c_str(), passphrase.length()); memcpy(input + passphrase.length(), &challenge[0], challenge.size()); crypto_hash_sha256(&response.data[0], input, inputlen); return response; }
int main() { struct stat st; int ch; if (fstat(0,&st) == 0) { input = mmap(0,st.st_size,PROT_READ,MAP_SHARED,0,0); if (input != MAP_FAILED) { crypto_hash_sha256(h,input,st.st_size); h_print(); return 0; } } input = 0; inputalloc = 0; inputlen = 0; while ((ch = getchar()) != EOF) { if (inputlen >= inputalloc) { void *newinput; while (inputlen >= inputalloc) inputalloc = inputalloc * 2 + 1; if (posix_memalign(&newinput,16,inputalloc) != 0) return 111; memcpy(newinput,input,inputlen); free(input); input = newinput; } input[inputlen++] = ch; } crypto_hash_sha256(h,input,inputlen); h_print(); return 0; }
void random_oracle(unsigned char *c_bin, double v[PARAM_M], const unsigned char *m, unsigned long long mlen) { int32_t t[PARAM_M]; unsigned long long i; unsigned char buf[PARAM_M+mlen]; compress_v(t, v); for(i=0; i<PARAM_M; i++) buf[i] = t[i]; for(i=0; i<mlen; i++) buf[i+PARAM_M] = m[i]; crypto_hash_sha256(c_bin, buf, PARAM_M+mlen); }
static inline void getPasswordHash_typeOne(uint8_t output[32], uint16_t derivations, struct CryptoAuth_Auth* auth) { Bits_memcpyConst(output, auth->secret, 32); if (derivations) { union { uint8_t bytes[2]; uint8_t asShort; } deriv = { .asShort = derivations }; output[0] ^= deriv.bytes[0]; output[1] ^= deriv.bytes[1]; crypto_hash_sha256(output, output, 32); } }
int crypto_sign( unsigned char *sm,unsigned long long *smlen, const unsigned char *m,unsigned long long mlen, const unsigned char *sk ) { unsigned char h[32]; int i; crypto_hash_sha256(h,m,mlen); if (signedshortmessage(sm,smlen,h,SHORTMESSAGE_BYTES,sk,SECRETKEY_BYTES) < 0) return -1; for (i = 0;i < mlen;++i) { sm[*smlen] = m[i]; ++*smlen; } return 0; }
/** * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). */ void PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) { uint8_t key[32] = {0}; size_t i; uint8_t salt_and_ivec[saltlen + 4]; uint8_t U[32]; uint8_t T[32]; uint64_t j; int k; size_t clen; if (passwdlen > 32) { /* For some reason libsodium allows 64byte keys meaning keys * between 32byte and 64bytes are not compatible with libsodium. toxencryptsave should only give 32byte passwds so this isn't an issue here.*/ crypto_hash_sha256(key, passwd, passwdlen); } else { memcpy(key, passwd, passwdlen); } memcpy(salt_and_ivec, salt, saltlen); for (i = 0; i * 32 < dkLen; i++) { be32enc(salt_and_ivec + saltlen, (uint32_t)(i + 1)); crypto_auth_hmacsha256(U, salt_and_ivec, sizeof(salt_and_ivec), key); memcpy(T, U, 32); for (j = 2; j <= c; j++) { crypto_auth_hmacsha256(U, U, 32, key); for (k = 0; k < 32; k++) { T[k] ^= U[k]; } } clen = dkLen - i * 32; if (clen > 32) { clen = 32; } memcpy(&buf[i * 32], T, clen); } sodium_memzero((void *) key, sizeof(key)); }
QString ClientConfiguration::toBackup(QString const& password) const { QByteArray encryptionKey(BACKUP_ENCRYPTION_KEY_BYTES, 0x00); // Generate a Salt QByteArray salt(BACKUP_SALT_BYTES, 0x00); randombytes_buf(salt.data(), BACKUP_SALT_BYTES); // Convert the password into bytes QByteArray password8Bit = password.toUtf8(); // Generate the encryption key for the Backup from the Salt and the Password PKCS5_PBKDF2_HMAC(reinterpret_cast<unsigned char*>(password8Bit.data()), password8Bit.size(), reinterpret_cast<unsigned char*>(salt.data()), BACKUP_SALT_BYTES, BACKUP_KEY_PBKDF_ITERATIONS, BACKUP_ENCRYPTION_KEY_BYTES, reinterpret_cast<unsigned char*>(encryptionKey.data())); QByteArray nonceBytes(crypto_stream_NONCEBYTES, 0x00); // The backup content QByteArray clientId(IdentityHelper::uint64ToIdentityString(getClientIdentity().getContactId()).toLatin1()); if (clientId.size() != BACKUP_IDENTITY_BYTES) { throw InternalErrorException() << QString("Could not build backup - invalid client identity length (%1 vs. %2 Bytes).").arg(clientId.size()).arg(BACKUP_IDENTITY_BYTES).toStdString(); } QByteArray clientSecKey(getClientLongTermKeyPair().getPrivateKey()); if (clientSecKey.size() != PROTO_KEY_LENGTH_BYTES) { throw InternalErrorException() << QString("Could not build backup - invalid client secret key length (%1 vs. %2 Bytes).").arg(clientSecKey.size()).arg(PROTO_KEY_LENGTH_BYTES).toStdString(); } QByteArray backup(salt); backup.append(clientId); backup.append(clientSecKey); // Compute Hash QByteArray controlHash(crypto_hash_sha256_BYTES, 0x00); crypto_hash_sha256(reinterpret_cast<unsigned char*>(controlHash.data()), reinterpret_cast<unsigned char*>(backup.data() + BACKUP_SALT_BYTES), BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES); backup.append(controlHash.left(BACKUP_HASH_BYTES)); if (backup.size() != (BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + BACKUP_HASH_BYTES)) { throw InternalErrorException() << QString("Could not build backup - invalid packet length (%1 vs. %2 Bytes).").arg(clientSecKey.size()).arg(BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + BACKUP_HASH_BYTES).toStdString(); } // The Backup is build from SALT + IDENTITY + KEY + HASH crypto_stream_xor(reinterpret_cast<unsigned char*>(backup.data() + BACKUP_SALT_BYTES), reinterpret_cast<unsigned char*>(backup.data() + BACKUP_SALT_BYTES), BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + BACKUP_HASH_BYTES, reinterpret_cast<unsigned char*>(nonceBytes.data()), reinterpret_cast<unsigned char*>(encryptionKey.data())); // Encode in Base32 return Base32::encodeBase32Sequence(backup); }
/* * AS of 16/01/2014 I'm using scrypt() instead of my crafted key * derivation function. However, I create a hash from the pcp_scrypt() * result anyway because I need a curve25519 secret. */ byte *pcp_derivekey(PCPCTX *ptx, char *passphrase, byte *nonce) { byte *key = smalloc(crypto_secretbox_KEYBYTES); size_t plen = strnlen(passphrase, 255); /* create the scrypt hash */ byte *scrypted = pcp_scrypt(ptx, passphrase, plen, nonce, LNONCE); /* make a hash from the scrypt() result */ crypto_hash_sha256(key, (byte*)scrypted, 64); /* turn the 32byte hash into a secret key */ key[0] &= 248; key[31] &= 127; key[31] |= 64; /* done */ sfree(scrypted); return key; }
int main(void) { int i; crypto_stream(output, 4194304, nonce, firstkey); crypto_hash_sha256(h, output, sizeof output); for (i = 0; i < 32; ++i) printf("%02x", h[i]); printf("\n"); assert(crypto_stream_keybytes() > 0U); assert(crypto_stream_noncebytes() > 0U); assert(strcmp(crypto_stream_primitive(), "xsalsa20") == 0); assert(crypto_stream_keybytes() == crypto_stream_xsalsa20_keybytes()); assert(crypto_stream_noncebytes() == crypto_stream_xsalsa20_noncebytes()); return 0; }
ClientConfiguration::BackupData ClientConfiguration::fromBackup(QString const& backup, QString const& password) { QByteArray decodedBase32 = Base32::decodeBase32Sequence(backup); if (decodedBase32.size() != BACKUP_DECODED_BYTES) { throw IllegalArgumentException() << "Invalid Backup: Size of decoded Backup String is incorrect (" << decodedBase32.size() << " Bytes instead of " << BACKUP_DECODED_BYTES << " Bytes)."; } unsigned char encryptionKey[BACKUP_ENCRYPTION_KEY_BYTES]; sodium_memzero(encryptionKey, BACKUP_ENCRYPTION_KEY_BYTES); // The pointer to the base32-decoded Backup unsigned char* decodedBase32Ptr = reinterpret_cast<unsigned char*>(decodedBase32.data()); // The Salt used in the PBKDF2 Key Derivation process is embedded in the first 8 bytes of the Backup. QByteArray password8Bit = password.toUtf8(); PKCS5_PBKDF2_HMAC(reinterpret_cast<unsigned char*>(password8Bit.data()), password8Bit.size(), decodedBase32Ptr, BACKUP_SALT_BYTES, BACKUP_KEY_PBKDF_ITERATIONS, BACKUP_ENCRYPTION_KEY_BYTES, encryptionKey); unsigned char nonceBytes[crypto_stream_NONCEBYTES]; sodium_memzero(nonceBytes, crypto_stream_NONCEBYTES); crypto_stream_xor(&decodedBase32Ptr[BACKUP_SALT_BYTES], &decodedBase32Ptr[BACKUP_SALT_BYTES], BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + BACKUP_HASH_BYTES, nonceBytes, encryptionKey); // The last two bytes of the Backup contain the truncated SHA-256 Hash over the identity and its Private Key. unsigned char controlHash[crypto_hash_sha256_BYTES]; sodium_memzero(controlHash, crypto_hash_sha256_BYTES); crypto_hash_sha256(controlHash, &(decodedBase32Ptr[BACKUP_SALT_BYTES]), BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES); if (sodium_memcmp(&(decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES]), controlHash, BACKUP_HASH_BYTES) != 0) { throw IllegalArgumentException() << "Decryption of Backup failed: Invalid Control Hash (" << controlHash[0] << controlHash[1] << " vs. " << decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES] << decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES + PROTO_KEY_LENGTH_BYTES + 1] << ")."; } unsigned char derivedPublicKey[PROTO_KEY_LENGTH_BYTES]; crypto_scalarmult_base(derivedPublicKey, &decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES]); KeyPair kp = KeyPair::fromArrays(derivedPublicKey, &decodedBase32Ptr[BACKUP_SALT_BYTES + BACKUP_IDENTITY_BYTES]); QString identityString(QByteArray(reinterpret_cast<char*>(&decodedBase32Ptr[BACKUP_SALT_BYTES]), BACKUP_IDENTITY_BYTES)); if (!isValidIdentity(identityString)) { throw IllegalArgumentException() << "Invalid ClientConfiguration: Decryption of Backup failed: Not a valid Identity."; } return BackupData(ContactId(identityString.toUtf8()), kp); }
/** * Get a shared secret. * * @param outputSecret an array to place the shared secret in. * @param myPrivateKey * @param herPublicKey * @param logger * @param passwordHash a 32 byte value known to both ends, this must be provably pseudorandom * the first 32 bytes of a sha256 output from hashing a password is ok, * whatever she happens to send me in the Auth field is NOT ok. * If this field is null, the secret will be generated without the password. */ static inline void getSharedSecret(uint8_t outputSecret[32], uint8_t myPrivateKey[32], uint8_t herPublicKey[32], uint8_t passwordHash[32], struct Log* logger) { if (passwordHash == NULL) { crypto_box_curve25519xsalsa20poly1305_beforenm(outputSecret, herPublicKey, myPrivateKey); } else { union { struct { uint8_t key[32]; uint8_t passwd[32]; } components; uint8_t bytes[64]; } buff; crypto_scalarmult_curve25519(buff.components.key, myPrivateKey, herPublicKey); Bits_memcpyConst(buff.components.passwd, passwordHash, 32); crypto_hash_sha256(outputSecret, buff.bytes, 64); } #ifdef Log_KEYS uint8_t myPublicKeyHex[65]; printHexPubKey(myPublicKeyHex, myPrivateKey); uint8_t herPublicKeyHex[65]; printHexKey(herPublicKeyHex, herPublicKey); uint8_t passwordHashHex[65]; printHexKey(passwordHashHex, passwordHash); uint8_t outputSecretHex[65] = "NULL"; printHexKey(outputSecretHex, outputSecret); Log_keys(logger, "Generated a shared secret:\n" " myPublicKey=%s\n" " herPublicKey=%s\n" " passwordHash=%s\n" " outputSecret=%s\n", myPublicKeyHex, herPublicKeyHex, passwordHashHex, outputSecretHex); #endif }
int crypto_sign_open( unsigned char *m,unsigned long long *mlen, const unsigned char *sm,unsigned long long smlen, const unsigned char *pk ) { unsigned char h[32]; unsigned long long hlen; int i; unsigned char hcheck[32]; unsigned char hchecksum; if (smlen < SIGNATURE_BYTES) return -100; i = shortmessagesigned(h,&hlen,sm,SIGNATURE_BYTES,pk,PUBLICKEY_BYTES); if (i < 0) return i; for (i = SIGNATURE_BYTES;i < smlen;++i) m[i - SIGNATURE_BYTES] = sm[i]; *mlen = smlen - SIGNATURE_BYTES; crypto_hash_sha256(hcheck,m,*mlen); hchecksum = 0; for (i = 0;i < SHORTMESSAGE_BYTES;++i) hchecksum |= (hcheck[i] ^ h[i]); if (hchecksum) return -100; return 0; }
void crypto_sha256(uint8_t *hash, const uint8_t *data, size_t length) { crypto_hash_sha256(hash, data, length); }
/** * send a message */ static void adminChannelSendData(struct Admin* admin, uint32_t channelNum, const void *data, uint32_t length) { /* if this changes, we need to fragment the messages * into MAX_MESSAGE_SIZE chunks */ Assert_compileTime(MAX_API_REQUEST_SIZE == MAX_MESSAGE_SIZE); Assert_true(length <= MAX_MESSAGE_SIZE); struct Admin_MessageHeader header = { .magic = admin->pipeMagic, .length = length, .channelNum = channelNum }; const uint8_t* buf = (const uint8_t*) data; // TODO: check result, buffer writes write(admin->outFd, &header, Admin_MessageHeader_SIZE); if (length > 0) { write(admin->outFd, buf, length); } } /** * public function to send responses */ void Admin_sendMessage(Dict* message, String* txid, struct Admin* admin) { if (!admin) { return; } Assert_true(txid); uint32_t channelNum; struct Admin_Channel* channel = adminChannelFindByTxid(admin, txid, &channelNum); if (!channel) { // txid too short, invalid channel number, closed channel or not matching serial Log_debug(admin->logger, "Dropped response because channel isn't open anymore."); return; } uint8_t buff[MAX_API_REQUEST_SIZE]; uint8_t allocBuff[256]; struct Allocator* allocator = BufferAllocator_new(allocBuff, 256); // Bounce back the user-supplied txid. String userTxid = { .bytes = txid->bytes + Admin_TxidPrefix_SIZE, .len = txid->len - Admin_TxidPrefix_SIZE }; if (txid->len > Admin_TxidPrefix_SIZE) { Dict_putString(message, TXID, &userTxid, allocator); } struct Writer* w = ArrayWriter_new(buff, sizeof(buff), allocator); StandardBencSerializer_get()->serializeDictionary(w, message); adminChannelSendData(admin, channelNum, buff, w->bytesWritten(w)); } /** * close a channel (for example if an error happened or we received non-empty * messages on a invalid channel number) * also used to cleanup if we receive a close message */ static void adminChannelClose(struct Admin* admin, uint32_t channelNum) { struct Admin_Channel* channel = adminChannelFindById(admin, channelNum); if (channel) { switch (channel->state) { case Admin_ChannelState_OPEN: break; case Admin_ChannelState_CLOSED: case Admin_ChannelState_WAIT_FOR_CLOSE: return; // already sent close, nothing to do } channel->state = Admin_ChannelState_WAIT_FOR_CLOSE; // clean up bufers channel->bufferLen = 0; channel->buffer = NULL; if (channel->allocator) { channel->allocator->free(channel->allocator); channel->allocator = NULL; } } adminChannelSendData(admin, channelNum, NULL, 0); } /** * handle a received channel close (the received header is in admin->messageHeader) * as invalid channels are never OPEN we never have to ACK a close on them */ static void adminChannelHandleClose(struct Admin* admin) { uint32_t channelNum = admin->messageHeader.channelNum; struct Admin_Channel* channel = adminChannelFindById(admin, channelNum); if (channel) { switch (channel->state) { case Admin_ChannelState_OPEN: // close active channel adminChannelClose(admin, channelNum); // now the state is WAIT_FOR_CLOSE, set it to CLOSED channel->state = Admin_ChannelState_CLOSED; break; case Admin_ChannelState_WAIT_FOR_CLOSE: channel->state = Admin_ChannelState_CLOSED; channel->serial++; break; case Admin_ChannelState_CLOSED: // nothing to do break; } } } static inline bool authValid(Dict* message, uint8_t* buffer, uint32_t length, struct Admin* admin) { String* cookieStr = Dict_getString(message, String_CONST("cookie")); uint32_t cookie = (cookieStr != NULL) ? strtoll(cookieStr->bytes, NULL, 10) : 0; if (!cookie) { int64_t* cookieInt = Dict_getInt(message, String_CONST("cookie")); cookie = (cookieInt) ? *cookieInt : 0; } uint64_t nowSecs = Time_currentTimeSeconds(admin->eventBase); String* submittedHash = Dict_getString(message, String_CONST("hash")); if (cookie > nowSecs || cookie < nowSecs - 20 || !submittedHash || submittedHash->len != 64) { return false; } uint8_t* hashPtr = (uint8_t*) strstr((char*) buffer, submittedHash->bytes); if (!hashPtr || !admin->password) { return false; } uint8_t passAndCookie[64]; snprintf((char*) passAndCookie, 64, "%s%u", admin->password->bytes, cookie); uint8_t hash[32]; crypto_hash_sha256(hash, passAndCookie, strlen((char*) passAndCookie)); Hex_encode(hashPtr, 64, hash, 32); crypto_hash_sha256(hash, buffer, length); Hex_encode(hashPtr, 64, hash, 32); return memcmp(hashPtr, submittedHash->bytes, 64) == 0; }
const char *checksum_compute(void) { long long i; long long j; for (i = 0; i < CHECKSUM_BYTES; ++i) { long long mlen = i; long long klen = crypto_auth_KEYBYTES; long long hlen = crypto_auth_BYTES; for (j = -16; j < 0; ++j) h[j] = rand(); for (j = -16; j < 0; ++j) k[j] = rand(); for (j = -16; j < 0; ++j) m[j] = rand(); for (j = hlen; j < hlen + 16; ++j) h[j] = rand(); for (j = klen; j < klen + 16; ++j) k[j] = rand(); for (j = mlen; j < mlen + 16; ++j) m[j] = rand(); for (j = -16; j < hlen + 16; ++j) h2[j] = h[j]; for (j = -16; j < klen + 16; ++j) k2[j] = k[j]; for (j = -16; j < mlen + 16; ++j) m2[j] = m[j]; if (crypto_auth(h,m,mlen,k) != 0) return "crypto_auth returns nonzero"; for (j = -16; j < klen + 16; ++j) if (k[j] != k2[j]) return "crypto_auth overwrites k"; for (j = -16; j < mlen + 16; ++j) if (m[j] != m2[j]) return "crypto_auth overwrites m"; for (j = -16; j < 0; ++j) if (h[j] != h2[j]) return "crypto_auth writes before output"; for (j = hlen; j < hlen + 16; ++j) if (h[j] != h2[j]) return "crypto_auth writes after output"; for (j = -16; j < 0; ++j) h[j] = rand(); for (j = -16; j < 0; ++j) k[j] = rand(); for (j = -16; j < 0; ++j) m[j] = rand(); for (j = hlen; j < hlen + 16; ++j) h[j] = rand(); for (j = klen; j < klen + 16; ++j) k[j] = rand(); for (j = mlen; j < mlen + 16; ++j) m[j] = rand(); for (j = -16; j < hlen + 16; ++j) h2[j] = h[j]; for (j = -16; j < klen + 16; ++j) k2[j] = k[j]; for (j = -16; j < mlen + 16; ++j) m2[j] = m[j]; if (crypto_auth(m2,m2,mlen,k) != 0) return "crypto_auth returns nonzero"; for (j = 0; j < hlen; ++j) if (m2[j] != h[j]) return "crypto_auth does not handle m overlap"; for (j = 0; j < hlen; ++j) m2[j] = m[j]; if (crypto_auth(k2,m2,mlen,k2) != 0) return "crypto_auth returns nonzero"; for (j = 0; j < hlen; ++j) if (k2[j] != h[j]) return "crypto_auth does not handle k overlap"; for (j = 0; j < hlen; ++j) k2[j] = k[j]; if (crypto_auth_verify(h,m,mlen,k) != 0) return "crypto_auth_verify returns nonzero"; for (j = -16; j < hlen + 16; ++j) if (h[j] != h2[j]) return "crypto_auth overwrites h"; for (j = -16; j < klen + 16; ++j) if (k[j] != k2[j]) return "crypto_auth overwrites k"; for (j = -16; j < mlen + 16; ++j) if (m[j] != m2[j]) return "crypto_auth overwrites m"; crypto_hash_sha256(h2,h,hlen); for (j = 0; j < klen; ++j) k[j] ^= h2[j % 32]; if (crypto_auth(h,m,mlen,k) != 0) return "crypto_auth returns nonzero"; if (crypto_auth_verify(h,m,mlen,k) != 0) return "crypto_auth_verify returns nonzero"; crypto_hash_sha256(h2,h,hlen); for (j = 0; j < mlen; ++j) m[j] ^= h2[j % 32]; m[mlen] = h2[0]; } if (crypto_auth(h,m,CHECKSUM_BYTES,k) != 0) return "crypto_auth returns nonzero"; if (crypto_auth_verify(h,m,CHECKSUM_BYTES,k) != 0) return "crypto_auth_verify returns nonzero"; sodium_bin2hex(checksum, sizeof checksum, h, crypto_auth_BYTES); return 0; }
byte *pcpkey_getchecksum(pcp_key_t *k) { byte *hash = ucmalloc(32); crypto_hash_sha256(hash, k->pub, LBOXPUB); return hash; }
SODIUM_EXPORT int crypto_hash_sha256_ref(unsigned char *out, const unsigned char *in, unsigned long long inlen) { return crypto_hash_sha256(out, in, inlen); }