C: implementing a Sha512 encryption with crypt(3) - c

As the title is saying I want to implement a simple Sha512 encryption with the C function crypt(3).
I have pretty much copied the examplecode from the GNU, even though I know the salt calculation isn`t very good. Also I changed the $1$ to the $6$, since the manpage of crypt says that this would create an SHA512 hash.
Anyway the output seems very strange to me, so I am asking if there is anything wrong with my code:
This is pretty much the function:
static char* hashStr(char *str) {
unsigned long seed[2];
char salt[] = "$6$........";
const char *const seedchars =
"./0123456789ABCDEFGHIJKLMNOPQRST"
"UVWXYZabcdefghijklmnopqrstuvwxyz";
seed[0] = time(NULL);
seed[1] = getpid() ^ (seed[0] >> 14 & 0x30000);
// Turn it into printable characters from `seedchars'.
for (int i = 0; i < 8; i++) {
salt[3+i] = seedchars[(seed[i/5] >> (i%5)*6) & 0x3f];
}
return crypt(str, salt);
}
Heres some output:
Bro -> $6$9AcWGmwG$5faOmA7QpXQ/MMmbFAT085HraONeaMYlTcBg09WmQUpSI.PkcrcDQiXCetyjuIK3sr3H5cIFyxHD.fywr9UfY/
Homie -> $6$BAcWGnwG$KUPLOdpa8QgF.cVljBXYl62lL9zejDW/ZWENUoC90jO4NinNc1Itk7Z1Zo3myogmHR/YPwoc2cqfjBL0cf.Ht0
hey -> $6$IAcWGowG$47WGhO6Hco9DOc0rnxu/KEttLvjv4wH6vJX8qj6hALr0Wa1/YQb0JETEcRgpe9.cPvwOBjQduLZn17gwSXM86.
What makes me wonder if the output is legit is especially that theres this &6& at the beginning every time.

As you can see here crypt(3) return:
$id$salt$encrypted
That's why you get $6$8chars$...

Related

Using a c-program to read an NMEA-string

I am trying to make a c-program that will will a string, but I want it only to read a very small part of it.
The NMEA-telegram that I try to read is $WIXDR, and do receive the necessary strings.
Here's 2 examples of strings that I get into the CPU:
$WIXDR,C,1.9,C,0,H,83.2,P,0,P,1023.9,H,0*46
$WIXDR,V,0.01,M,0,Z,10,s,0,R,0.8,M,0,V,0.0,M,1,Z,0,s,1,R,0.0,M,1,R,89.9,M,2,R,0.0,M,3*60
If it were only 1 string (not both C and V), this would not be a problem for me.
The problem here is that it's 2 seperate strings. One with the temperature, and one with rain-info.
The only thing that I'm interested in is the value "1.9" from
$WIXDR,C,1.9,C,0......
Here's what I have so far:
void ProcessXDR(char* buffPtr)
{
char valueBuff[10];
int result, x;
float OutSideTemp;
USHORT uOutSideTemp;
// char charTemperature, charRain
IODBerr eCode;
//Outside Temperature
result = ReadAsciiVariable(buffPtr, &valueBuff[0], &buffPtr, sizeof(valueBuff));
sscanf(&valueBuff[0],"%f",&OutSideTemp);
OutSideTemp *= 10;
uOutSideTemp = (USHORT)OutSideTemp;
eCode = IODBWrite(ANALOG_IN,REG_COM_XDR,1,&uOutSideTemp,NULL);
}
// XDR ...
if(!strcmp(&nmeaHeader[0],"$WIXDR"))
{
if(PrintoutEnable)printf("XDR\n");
ProcessXDR(buffPtr);
Timer[TIMER_XDR] = 1200; // Update every minute
ComStateXDR = 1;
eCode = IODBWrite(DISCRETE_IN,REG_COM_STATE_XDR,1,&ComStateXDR,NULL);
}
There's more, but this is the main part that I have.
I have found the answer to my own question. The code that would do as I intented is as follows:
What my little code does, is to look for the letter C, and if the C is found, it will take the value after it and put it into "OutSideTemp". The reason I had to look for C is that there is also a similar string received with the letter V (Rain).
If someone have any input in a way it could be better, I don't mind, but this little piece here does what I need it to do.
Here's to example telegrams I receive (I wanted the value 3.0 to be put into "OutSideTemp"):
$WIXDR,C,3.0,C,0,H,59.2,P,0,P,1026.9,H,04F
$WIXDR,V,0.00,M,0,Z,0,s,0,R,0.0,M,0,V,0.0,M,1,Z,0,s,1,R,0.0,M,1,R,89.9,M,2,R,0.0,M,358
void ProcessXDR(char* buffPtr)
{
char valueBuff[10];
int result, x;
float OutSideTemp;
USHORT uOutSideTemp;
// char charTemperature, charRain
IODBerr eCode;
// Look for "C"
result = ReadAsciiVariable(buffPtr, &valueBuff[0], &buffPtr, sizeof(valueBuff));
// sscanf(&valueBuff[0],"%f",&charTemperature);
if (valueBuff[0] == 'C')
//Outside Temperature
result = ReadAsciiVariable(buffPtr, &valueBuff[0], &buffPtr, sizeof(valueBuff));
sscanf(&valueBuff[0],"%f",&OutSideTemp);
OutSideTemp *= 10;
uOutSideTemp = (USHORT)OutSideTemp;
eCode = IODBWrite(ANALOG_IN,REG_COM_XDR,1,&uOutSideTemp,NULL);
}

CS50 pset3 Music segmentation fault

Today I finished the music project, or at least I think I've finished it.
On helper.c when I run make it makes both notes and synthesizer files and with no errors. But when I want to run ./notes it gives me segmentation fault error. Even when I ran the program with check50 it gave me this error:
failed to execute program due to segmentation fault
I personally think it might be because of turning string to int or the way I got the notes from the string. First I introduced one string for taking the note and one int for taking the ovtav of the note.
The string note is something like D4 or C#4
So I will just copy this part, to check with you if I've done it correctly.
string noteletter="";
int noteoctav;
if (strlen(note) == 3)
{
noteletter[0] = note[0];
noteletter[1] = note[1];
noteoctav = note[2] - '0';
}
if (strlen(note)== 2)
{
noteletter[0] = note[0];
noteoctav = note[1] - '0';
}
Update
Here I've added the full code so you can see what I am trying to do.
Two problems I can see (assuming string is a typedef of char*)
if noteletter has a length of 0 (value = "") then what do you think noteletter[1] is doing?
Even if noteletter was set to something bigger (e.g. noteletter = "ABC";) - writing to a literal string is undefined behavior.
Try char noteletter[3] = { 0 }; to get something that (at a quick glance) looks big enough.
Another possible issue: if note is NULL or invalid then strlen(note) is not safe.
(Posted answer on behalf of the question author)
My problem was that I defined noteletter as string. I changed that part to
char noteletter[4];
int noteoctav;
if (strlen(note) == 3)
{
noteletter[0] = note[0];
noteletter[1] = note[1];
noteletter[2] = '\0';
noteoctav = note[2] - '0';
}
if (strlen(note)== 2)
{
noteletter[0] = note[0];
noteletter[1] = '\0';
noteoctav = note[1] - '0';
}
and now it works :)

ASN1_INTEGER to ASN1_STRING

I am using openssl to get data about x509 certificate.
Is there a way to convert ASN1_INTEGER to ASN1_STRING, which can than easily be transformed to char array? Is there a way to convert it to any other human readable format?
EDIT: I'm using openssl compiled for iOS, as I am having the iOS project. Here is the code I am using to extract the serial number from the certificate:
ASN1_INTEGER *serial = X509_get_serialNumber(certificateX509);
long value = ASN1_INTEGER_get(serial);
NSLog(#"Serial %ld", value);
certificateX509 is a valid X509 object and I have managed to get some other fields from it (issuer name, expiry date and so on)
EDIT 2:
I finally came to a solution, which may not be the most straightforward one:
ASN1_INTEGER *serial = X509_get_serialNumber(certificateX509);
BIGNUM *bnser = ASN1_INTEGER_to_BN(serial, NULL);
int n = BN_num_bytes(bnser);
unsigned char outbuf[n];
int bin = BN_bn2bin(bnser, outbuf);
char *hexbuf = (char*) outbuf;
hexBuf then contains characters whose value needs to be read as hex integer in order to retrieve logical values.
I use NSMutableString to create a human readable string:
NSMutableString *str = [[NSMutableString alloc] init];
for (int i=0; i<n; i++) {
NSString *temp = [NSString stringWithFormat:#"%.6x", hexbuf[i]];
[str appendString:[NSString stringWithFormat:#"%# ", temp]];
}
If there is a simpler way, I would really like to know it.
The ascii hex conversion be done more simply using the built in BN_bn2hex(BIGNUM *) function
ASN1_INTEGER *serial = X509_get_serialNumber(certificateX509);
BIGNUM *bnser = ASN1_INTEGER_to_BN(serial, NULL);
char *asciiHex = BN_bn2hex(bnser);
One possibility is that you can extract the value of the ASN1_INTEGER as a normal C integer:
#include <openssl/asn1.h>
#include <stdio.h>
int main(int argc, char** argv) {
long value;
ASN1_INTEGER asn1int = {0};
ASN1_INTEGER_set(&asn1int, 42);
value = ASN1_INTEGER_get(&asn1int);
printf("The value is %ld.\n", value);
return 0;
}
Compiled like this:
gcc -Wall -o sploots sploots.c -lcrypto
this produces the output:
The value is 42.
To have the value as a string in an array of char, use snprintf.
I suspect there are also possibilities for using the BIO printing routines to dump the value to a BIO of some sort (perhaps a memory BIO). However, this approach seems simpler.
The way I arrived at this answer is that I looked through the OpenSSL headers for ASN1_INTEGER. After looking around for suitable APIs for a BIO-based solution, I noticed the ASN1_INTEGER_get function.
Looking around in OpenSSL header files is typically the way I learn how to use OpenSSL, since so much of the API is undocumented or incorrectly or incompletely documented.
I finally came to a solution, which may not be the most straightforward one:
ASN1_INTEGER *serial = X509_get_serialNumber(certificateX509);
BIGNUM *bnser = ASN1_INTEGER_to_BN(serial, NULL);
int n = BN_num_bytes(bnser);
unsigned char outbuf[n];
int bin = BN_bn2bin(bnser, outbuf);
char *hexBuf = (char*) outbuf;
hexBuf then contains characters whose value needs to be read as hex integer in order to retrieve logical values.
I use NSMutableString to create a human readable string:
NSMutableString *str = [[NSMutableString alloc] init];
for (int i=0; i<n; i++) {
NSString *temp = [NSString stringWithFormat:#"%.6x", hexbuf[i]];
[str appendString:[NSString stringWithFormat:#"%# ", temp]];
}
If you just want a readable NSString, BN_bn2dec is more consize than BN_bn2hex or BN_bn2bin.
No need to mess with hex encoding.
Here's my way, in iOS/ObjC, using pod 'OpenSSL-Universal', '1.0.2.10' :
ASN1_INTEGER *serialAsn1 = X509_get_serialNumber(certX509);
BIGNUM *serialBigNumber = ASN1_INTEGER_to_BN(serialAsn1, NULL);
char *serialChar = BN_bn2dec(serialBigNumber);
NSString *serialString = [NSString stringWithCString:(const char *) serialChar
encoding:NSUTF8StringEncoding];
Cheers.
This solution worked for me to get the serial number in hex:
ASN1_INTEGER* serial = X509_get_serialNumber(X509_certificate_ptr);
BIGNUM* bn = ASN1_INTEGER_to_BN(serial, NULL);
if (!bn) {
// log here "Unable to convert ASN1INTEGER to BN";
return "";
}
char* hex = BN_bn2hex(bn);
if (!hex) {
// Log here "Unable to convert BN to hex string";
return "";
}
cout << hex; // this is your serial number. Can be converted using std::to_string()
BN_free(bn);
ASN1_INTEGER_free(serial);
OPENSSL_free(hex);
return serial_number;
Without error checking and memory management the code is basically:
ASN1_INTEGER* serial = X509_get_serialNumber(X509_certificate_ptr);
BIGNUM* bn = ASN1_INTEGER_to_BN(serial, NULL);
char* hex = BN_bn2hex(bn);

Missing characters from input stream from fastcgi request

I'm trying to develop simple RESTful api using FastCGI (and restcgi). When I tried to implement POST method I noticed that the input stream (representing request body) is wrong. I did a little test and looks like when I try to read the stream only every other character is received.
Body sent: name=john&surname=smith
Received: aejh&unm=mt
I've tried more clients just to make sure it's not the client messing with the data.
My code is:
int main(int argc, char* argv[]) {
// FastCGI initialization.
FCGX_Init();
FCGX_Request request;
FCGX_InitRequest(&request, 0, 0);
while (FCGX_Accept_r(&request) >= 0) {
// FastCGI request setup.
fcgi_streambuf fisbuf(request.in);
std::istream is(&fisbuf);
fcgi_streambuf fosbuf(request.out);
std::ostream os(&fosbuf);
std::string str;
is >> str;
std::cerr << str; // this way I can see it in apache error log
// restcgi code here
}
return 0;
}
I'm using fast_cgi module with apache (not sure if that makes any difference).
Any idea what am I doing wrong?
The problem is in fcgio.cpp
The fcgi_steambuf class is defined using char_type, but the int underflow() method downcasts its return value to (unsigned char), it should cast to (char_type).
I encountered this problem as well, on an unmodified Debian install.
I found that the problem went away if I supplied a buffer to the fcgi_streambuf constructor:
const size_t LEN = ... // whatever, it doesn't have to be big.
vector<char> v (LEN);
fcgi_streambuf buf (request.in, &v[0], v.size());
iostream in (&buf);
string s;
getline(in, s); // s now holds the correct data.
After finding no answer anywhere (not even FastCGI mailing list) I dumped the original fastcgi libraries and tried using fastcgi++ libraries instead. The problem disappeared. There are also other benefits - c++, more features, easier to use.
Use is.read() not is >> ...
Sample from restcgi documentation:
clen = strtol(clenstr, &clenstr, 10);
if (*clenstr)
{
cerr << "can't parse \"CONTENT_LENGTH="
<< FCGX_GetParam("CONTENT_LENGTH", request->envp)
<< "\"\n";
clen = STDIN_MAX;
}
// *always* put a cap on the amount of data that will be read
if (clen > STDIN_MAX) clen = STDIN_MAX;
*content = new char[clen];
is.read(*content, clen);
clen = is.gcount();

parsing/matching string occurrence in C

I have the following string:
const char *str = "\"This is just some random text\" 130 28194 \"Some other string\" \"String 3\""
I would like to get the the integer 28194 of course the integer varies, so I can't do strstr("20194").
So I was wondering what would be a good way to get that part of the string?
I was thinking to use #include <regex.h> which I already have a procedure to match regexp's but not sure how the regexp in C will look like using the POSIX style notation. [:alpha:]+[:digit:] and if performance will be an issue. Or will it be better using strchr,strstr?
Any ideas will be appreciate it
If you want to use regex, you can use:
const char *str = "\"This is just some random text\" 130 28194 \"Some other string\" \"String 3\"";
regex_t re;
regmatch_t matches[2];
int comp_ret = regcomp(&re, "([[:digit:]]+) \"", REG_EXTENDED);
if(comp_ret)
{
// Error occured. See regex.h
}
if(!regexec(&re, str, 2, matches, 0))
{
long long result = strtoll(str + matches[1].rm_so, NULL, 10);
printf("%lld\n", result);
}
else
{
// Didn't match
}
regfree(&re);
You're correct that there are other approaches.
EDIT: Changed to use non-optional repetition and show more error checking.

Resources