I'm looking for a function that will generate an "alphanumeric hash". Given a source string, it produces a determinate result string that can contain any letter a-z or digit 0-9, and cannot be reverse-engineered to produce the source. This will be used to generate passwords for a system based on secret data, so strings between 8 and 12 characters are ideal and a secure hash would also be ideal.
I'm thinking I can use a normal bitwise hash, XOR-fold it to 64 bits (if I use, for instance, SHA256) and then take the result 5 bits at a time (producing a number 0-31) and look up the character code to use from an indexed ordered collection. There are 26 letters and 10 digits meaning I'll have to leave a few out (probably removing characters that could be mistaken for others if handwritten). 64 bits, 5 bits at a time, will produce a 12-character string with 4 bits left over.
However, I'm worried about two things: first, introducing bias by taking a non-power-of-2 number of bits; and second, what to do with the leftover bits. Do I use them as-is knowing there will only be 16 possibilities, do I leave them off (and lose data possibly introducing bias), or do I incorporate one more bit to make a 13-character string (and where should the last bit come from)?
EDIT: Here's my current stab at it; it takes an enumerable of bytes (like the byte array produced by most hash algorithms) and returns a string:
/// <summary>
/// Converts an IEnumerable of bytes to a string representation which can have any lowercase letter a-z except for l, o, q and z, and any digit 0-9.
/// Uses 5 bits of the byte array at a time to generate numbers from 0 to 31, which are then translated to letters or numbers.
/// </summary>
/// <param name="toConvert">the byte array to convert.</param>
/// <returns>A string containing the alphanumeric case-insensitive representation of the bytes in the array.</returns>
public static string ToInsensitiveAlphaNumericString(this IEnumerable<byte> toConvert)
{
var chars = new[]
{
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'p', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};
var enumerator = toConvert.GetEnumerator();
enumerator.MoveNext();
int buffer = enumerator.Current;
short bufferLength = 8;
const int valueLength = 5;
var builder = new StringBuilder();
while (true)
{
var value = buffer >> (bufferLength - valueLength);
builder.Append(chars[value]);
buffer = buffer - (value << (bufferLength - valueLength));
bufferLength -= valueLength;
if(bufferLength < valueLength )
{
if (enumerator.MoveNext())
{
buffer = (buffer << 8) + enumerator.Current;
bufferLength += 8;
}
else
{
//here's the main question; to include, or not to include?
if (bufferLength > 0)
builder.Append(chars[buffer]);
break;
}
}
}
return builder.ToString();
}
How about generating your SHA256 and then Base36 encoding the result? No left over bits, no bias...
That way you have the cryptographic strength of a proven algorithm (remember to salt and use multiple hash iterations) along with the alphanumeric representation that you need.
If you just use those bits as they are (so that one character only has 16 possibilities), you still have your full 64 bits of entropy. If you're happy with 64 bits of entropy (which it sounds like you are), there's no reason to mind that one character has a restricted range.
If you have some reason (aesthetics?) to prefer that all of the characters have the full range, then you can drop those 4 bits, but you'll be taking yourself down to 60 bits of entropy. If you would have been happy with 8-character passwords, then it sounds like 60 bits is also plenty.
So whichever of those is easier should work fine.
Related
In VHDL, If X'1 => "0001", X'3 => "0011". i.e, 1 hex digit represents 4 binary values, how do i represent only 2 binary values in hex given that i have only a specific bit range in memory. In this case 2. For instance, the space left in memory can only take 2 bits. I know i can still use the initial representation and mask out either the two msb's or lsb's but is there another way ?
You can do this if you are using VHDL-2008:
2X"2" = "0010"
Further examples from web:
unsigned notation (default):
7UX"F" = "0001111" -- extend
7UX"0F" = "0001111" -- reduce
signed noataion:
7SX"F" = "1111111" -- extend
7SX"CF" = "1001111" -- reduce
How does this denary to binary program work? I am finding it hard to comprehend what is happening behind the code.
Can someone explain the lines 6 onwards?
Number = int(input("Hello. \n\nPlease enter a number to convert: "))
if Number < 0:
print ("Can't be less than 0")
else:
Remainder = 0
String = ""
while Number > 0:
Remainder = Number % 2
Number = Number // 2
String = str(Remainder) + String
print (String)
The idea is to separate out the last part of the binary number, stick it in a buffer, and then remove it from "Number". The method is general and can be used for other bases as well.
Start by looking at it as a dec -> dec "conversion" to understand the principle.
Let's say you have the number 174 (base10). If you want to parse out each individual piece (read as "digit") of it you can calculate the number modulo the base (10), then do an integer division to "remove" that digit from the number. I.e. 174%10 and 174//10 => (Number) 17|4 (Reminder). Next iteration you have 17 from the division and when you perform the same procedure, it'll split it up into 1|7. On the next iteration you'll get 0|1, and after that "Number" will be 0 (which is the exit condition for the loop (while Number > 0)).
In each iteration of the loop you take the remainder (which will be a single digit for the specific base you use (it's a basic property of how bases work)), convert it to a string and concatenate it with the string you had from previous iterations (note the order in the code!), and you'll get the converted number once you've divided your way down to zero.
As mentioned before, this works for any base; you can use base 16 to convert to hex (though you'll need to do some translations for digits above 9), octal (base 8), etc.
Python code for converting denary into binary
denary= int(input('Denary: '))
binary= [0,0,0,0]
while denary>0:
for n,i in enumerate(binary):
if denary//(2**(3-n))>=1:
binary[n]= 1
denary -= 2**(3-n)
print(denary)
print (binary)
I am making an html webpage that uses cgi to access a table/database in mysql. I input a .csv file containing info on my class schedule and the html displays it in the usual schedule table.
My problem is that I can't seem to use strcmp in my parsing cgi as it causes a server error. here is an excerpt of my code where I uses strcmp.
void parse2(char *queu)
{
//---------------------------------------------------------------
char *saveptr[1024];
char *subtoken;
char *Subject;
char *Day;
char *Start;
char *End;
char *Room;
char *Teacher;
int check = 1;
//---------------------------------------------------------------
subtoken = strtok_r(queu, ",", saveptr);
check = strcmp(subtoken, "\0");
printf("%d<br>", check);
if(check == 0){
printf("Error!");
} else {
Subject = subtoken;
Day = strtok_r(NULL, ",", saveptr);
Start = strtok_r(NULL, ",", saveptr);
End = strtok_r(NULL, ",", saveptr);
Room = strtok_r(NULL, ",", saveptr);
Teacher = strtok_r(NULL, ",", saveptr);
printf("%s\n<br/>%s\n<br/>%s\n<br/>%s\n<br/>%s\n<br/>%s\n", Subject, Day, Start, End, Room, Teacher);
//inputsql(Subject, Day, Start, End, Room, Teacher);
}
//---------------------------------------------------------------
}
Note that, I have tested this code and it works fine without me calling strcmp().
I am using strcmp() to prevent a line of unwanted characters, generated after the info when retrieved using POST method, from being entered into my database.
As you can see from the above code, I used strtok() to parse the line of info. Since the line of unwanted characters do not contain a comma (which is my delimiter) it should return a NULL value. correct?
Can anyone help me out? I welcome suggestions to use a different way on solving the problem I chose to solve using strcmp().
I think you should be checking subtoken == NULL, not strcmp(subtoken, "\0") == 0.
"\0" is a string containing a NUL byte, then another NUL (the terminator), so the standard library's string functions will just see an empty string. That's different to a NULL pointer (i.e. a pointer with value zero).
From STRTOK(3):
Each call to strtok() returns a pointer to a null-terminated string
containing the next token. This string does not include the
delimiting byte. If no more tokens are found, strtok() returns NULL.
I've made this small experimental program in Arduino to see how the functions lowByte() and highByte() work. What exactly are they supposed to return when passed a value?
On entering the character '9' in the serial monitor it prints the following:
9
0
218
255
How does that come? Also, the last 2 lines are being printed for all values inputted. Why is this happening?
int i=12;
void setup()
{
Serial.begin(9600);
}
void loop()
{
if(Serial.available())
{
i = Serial.read() - '0'; // conversion of character to number. eg, '9' becomes 9.
Serial.print(lowByte(i)); // send the low byte
Serial.print(highByte(i)); // send the high byte
}
}
If you have this data:
10101011 11001101 // original
// HighByte() get:
10101011
// LowByte() get:
11001101
An int is a 16-bit integer on Arduino. So you are reading the high and low part as a byte.
As the actual buffer is "9\n", that is why the second bit prints out 'funny' numbers due to subtracting the result with '0'.
Serial.print needs to be formatted to a byte output if that's what you want to see.
Try:
Serial.print(lowByte, BYTE)
In addition to Rafalenfs' answer, Should you provide a larger data type:
00000100 10101011 11001101 // original
// HighByte() will NOT return: 00000100, but will return:
10101011
// LowByte() will still return:
11001101
Highbyte() returns the second lowest bit (as specified by the documentation: https://www.arduino.cc/reference/en/language/functions/bits-and-bytes/highbyte/)
I am writing a sketch for Arduino that aims to convert a text string into binary 7-bit or 8-bit ASCII. For example, "Hello World" would become this 8-bit ASCII binary stream:
0100100001100101011011000110110001101111001000000111011101101111011100100110110001100100
As you can see, this is standard 7-bit ASCII padded with zeros to make it 8-bit ASCII. I don't mind which bit length I use as long as it's consistent once I've started. I've spent a couple of hours trying to work out a method to achieve that to no avail. The closest I have is something like this:
char text[] = "Hello world";
which when printed to the monitor like this:
Serial.println(text[0], BIN);
Gives me 1001000. However, this isn't at all padded (so "0" would simply be 0, not 0000000) and obviously this doesn't provide me with anything to work with, just something to look at! Does anyone have any advice for me?
You can use this as a starting point:
char inputChar = 'H';
// This will 'output' the binary representation of 'inputChar' as 8 characters of '1's and '0's, MSB first.
for ( uint8_t bitMask = 128; bitMask != 0; bitMask = bitMask >> 1 ) {
if ( inputChar & bitMask ) {
output('1');
} else {
output('0');
}
}