forked from technion/libscrypt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
crypto-mcf.c
64 lines (51 loc) · 1.48 KB
/
crypto-mcf.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <float.h>
#include <math.h>
#include "libscrypt.h"
/* Although log2 exists in GNU99 C, more portable code shouldn't use it
* Note that this function returns a float and hence is not compatible with the
* GNU prototype
*/
static double scrypt_log2( uint32_t n )
{
// log(n)/log(2) is log2.
double temp;
/* Using the temp variable keeps splint happy */
temp = log(2);
return (log((double)n) / temp);
}
int libscrypt_mcf(uint32_t N, uint32_t r, uint32_t p, char *salt, char *hash, char *mcf)
{
uint32_t params;
int s;
double t, t2, fracpart;
if(!mcf || !hash)
return 0;
/* Although larger values of r, p are valid in scrypt, this mcf format
* limits to 8 bits. If your number is larger, current computers will
* struggle
*/
if(r > (uint8_t)(-1) || p > (uint8_t)(-1))
return 0;
t = scrypt_log2(N);
/* The "whole numebr" check below is non-trivial due to precision
* issues, where you could printf("%d", (int)t) and find yourself
* looking at (expected value) -1
*/
fracpart = modf(t, &t2);
if(fracpart > DBL_EPSILON)
return 0;
params = (r << 8) + p;
params += (uint32_t)t << 16;
/* Using snprintf - not checking for overflows. We've already
* determined that mcf should be defined as at least SCRYPT_MCF_LEN
* in length
*/
s = snprintf(mcf, SCRYPT_MCF_LEN, SCRYPT_MCF_ID "$%06x$%s$%s", (unsigned int)params, salt, hash);
if (s > SCRYPT_MCF_LEN)
return 0;
return 1;
}