I would like to generate the mysql-password hash from js.
I know the method with php functions,
$p = "example";
echo("$p<br>");
$p2= sha1($p,true);
echo("$p2<br>"); //ĂI')s~űvŠ-Ëo?
$result = sha1($p2);
echo("$result<br>"); //*57237bb49761f29ab9724ba084e811d70c12393d - this is the same as password("example") in mysql
and I'm trying to do this in javascript.
here is located the sha1 function:
http://pajhome.org.uk/crypt/md5/sha1.html
this is the hex2bin function I use to give the same result as sha1("",true);
function hex2bin(hex)
{
var bytes = [], str;
for(var i=0; i< hex.length-1; i+=2)
bytes.push(parseInt(hex.substr(i, 2), 16));
return String.fromCharCode.apply(String, bytes);
}
but at the last step it does not work. What can be the problem?
var p = "example";
console.log(p);
var p2 = hex2bin(hex_sha1(p));
console.log(p); //ÃI')s~ûv©-Ëo? - SEEMS OK
var result = hex_sha1(p2);
console.log(result); //9a5355dce26b1adfa0bdbe9f2b2a6e5ae58e5c9d WRONG
Use http://code.google.com/p/crypto-js/#SHA-1 with 2 encodings.
Here is an example:
var password = "TestPassword";
var result = ("*"+CryptoJS.SHA1(CryptoJS.SHA1(password))).toUpperCase();
console.log("result : " + result);
Result will be *0F437A73F4E4014091B7360F60CF81271FB73180. If you check it with mysql password() it will be the same:
mysql> select password("TestPassword") as result;
+-------------------------------------------+
| result |
+-------------------------------------------+
| *0F437A73F4E4014091B7360F60CF81271FB73180 |
+-------------------------------------------+
SOLUTION 2017
Download file 2.5.3-crypto-sha1.js
https://code.google.com/archive/p/crypto-js/downloads
var key = '*' + Crypto.SHA1(Crypto.util.hexToBytes(Crypto.SHA1('test'))).toUpperCase();
key = *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29
Test in MySQL
SELECT PASSWORD('test') /* function */
UNION
SELECT '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29' /* Key generated by javascript */
UNION
select CONCAT('*', UPPER(SHA1(UNHEX(SHA1('test'))))); /* Logic for Password() function */
So, in the example above, you are invoking: hex_sha1(hex2bin(hex_sha1(string))). Are you sure that is correct? Why would you need hex_sha1 twice?
Few month ago, I needed SHA1 in my JS and found this: http://phpjs.org/functions/sha1:512
... and it worked pretty ok ;)
The solution (partly):
Well, as you suggested, the main problem was charset encoding. It seems that MySQL does not encode any data prior to hashing it. This does not represent problem when dealing it with hex data, however, MySQL's UNHEX(hex2bin in JS) returns some unreadable chars and if we encode the result using UTF8 that's where all breaks apart.
When I edited JS's SHA1 not to encode data to UTF8 at line (I only commented the line):
str = this.utf8_encode(str);
everything seemed ok. However, as soon as I supplied some UTF8 chars to input (such as Central European chars čćžšđ) it started failing again.
So, bottom line, if you disable UTF8 in JSs SHA1 function and do not supply UTF8 chars on input it works fine.
I'm sure there is a solution to this such as JS function that will decode UTF8 input so, JS could hash it properly.
Related
I have a project I'm working on that uses an API for it request, but in order to preform them I need to generate the token first.
Before the API was update everything was working, after the update I don't know how to adjust my code to make it work again.
This was the code that worked before the update (Android | Kotlin):
fun hmacHash(str: String, secret: String): String {
val sha256HMAC = Mac.getInstance("HmacSHA256")
val secretKey = SecretKeySpec(secret.toByteArray(), "HmacSHA256")
sha256HMAC.init(secretKey)
return convertToHex(sha256HMAC.doFinal(str.toByteArray()))
}
fun convertToHex(data: ByteArray): String {
val buf = StringBuilder()
for (b in data) {
var halfbyte = (b.toInt() shr 4) and (0x0F.toByte()).toInt()
var two_halfs = 0
do {
buf.append(if (halfbyte in 0..9) ('0'.toInt() + halfbyte).toChar() else ('a'.toInt() + (halfbyte - 10)).toChar())
halfbyte = (b and 0x0F).toInt()
} while (two_halfs++ < 1)
}
return buf.toString()
}
Which was equivalent to this PHP code:
hash_hmac('sha256', $string, $privateKey);
But now after the update the php code looks like this:
hash_hmac('sha256', $string, hex2bin($privateKey));
And I don't know how to adjust my code to make it work with this new change.
From what I can deduce, the PHP code made that change because $privateKey went from being plain text to being hex-encoded. So hex2bin was needed to change it back to plain text (hex2bin changes hex-encoded text to plain text; a confusingly named function if you ask me).
Since your secret is plain text, you don't need to change anything to match. But there are other ways to improve your code. For example, converting a byte array to a hex-encoded string is much easier than that.
fun hmacHash(str: String, secret: String): String {
val sha256HMAC = Mac.getInstance("HmacSHA256")
val bytes = secret.toByteArray()
val secretKey = SecretKeySpec(bytes, "HmacSHA256")
sha256HMAC.init(secretKey)
return convertToHex(sha256HMAC.doFinal(str.toByteArray()))
}
fun convertToHex(data: ByteArray): String =
data.joinToString("") { "%02x".format(it) }
I'm having a problem to insert a oriental character with bind variables in SQL Server.
i'm using MSSQL commands and PHP.
My PHP code is like this:
$sql = "
CREATE TABLE table_test
( id int
,nvarchar_latin nvarchar(255) collate sql_latin1_general_cp1_ci_as
);";
$stmt = mssql_query($sql);
$conn = mssql_connect("server","user","pass");
mssql_select_db('test')
$stmt = mssql_init('test..sp_chinese', $conn);
$id = 1;
$nvarchar_latin = '重建議';
mssql_bind($stmt, '#id' , $id , SQLINT1);
mssql_bind($stmt, #nvarchar_latin, $nvarchar_latin, SQLVARCHAR);
mssql_execute($stmt);
My procedure is like this:
ALTER PROCEDURE sp_chinese
#id int
,#nvarchar_latin nvarchar (255)
AS
BEGIN
INSERT INTO char_chines (id, nvarchar_latin)
VALUES (#id, #nvarchar_latin);
END
this work if I change the oriental characters for normal one.
if I run directly this insert, it work's fine:
INSERT INTO table_test (id, nvarchar_latin)
VALUES (1, '重建議');
So, cleary the problem is when I send the variable from PHP to SQL Server.
Anyone have a clue how to make this works? some casting or something?
Thanks!
A solution that uses just the PHP (or even JavaScript) is to convert the character to its HEX value and store that. I don't know if you want to go this route but and I don't have time to show you the code but here is the full theory:
A non-English character is detected, like so: 重
Convert to HEX value (Look here for starters. But a search for Javascript will help you find better ways to do this even in PHP): 14af
NOTE: That is not what 重 really is in HEX
Store in a way that you can convert back to its original value. For example how can you tell what this is: 0d3114af is it 0d - 31 - 14 - af OR is it 0d31 - 14af. You can use deliminators like | or a . but one way is to provide padding of 00 in front. An English character would be only 2 characters long like 31 or af non-English will be 4 like 14af. Knowing this you can just split every 4 characters and convert to their values.
Downside is you will need to change your Database to accommodate these changes.
[ UPDATE ] -----
Here is some JavaScript code to send you off in the right direction. This is completely possible to replicate in PHP. This does not search for characters though, its part of an encryption program so all it cares about is turning everything into HEX. English characters will be padded with 00 (This is my own code hence no link to source):
function toHex(data) {
var result = '';
// Loop through entire string of data character by character
for(var i=0;i<data.length;i++) {
// Convert UTF-16 Character to HEX, if it is a 2 chracter HEX add 00 padding in front
result += (data.charCodeAt(i) + 0x10000).toString(16).slice(1);
}
// Display the result for testing purposes
document.getElementById('two').value = result;
}
function fromHex(data) {
var result = '', block = '', pattern = /(00)/; // Pattern is the padding
for(var i=0;i<data.length;i = i+4) {
// Split into separate HEX blocks
block = data.substring(i,i+4);
// Remove 00 from a HEX block that was only 2 characters long
if(pattern.test(block)){
block = block.substring(2,4);
}
// HEX to UTF-16 Character
result += String.fromCharCode(parseInt(block,16));
}
// Display the result for testing purposes
document.getElementById('two').value = result;
}
Note: I am limited to PHP <-> VBA. Please do not suggest anything that requires an Excel Addon, or any other language/method.
I have a function that connect to a specified URL, submits data, and then retrieves other data. This works great. I'm trying to write it so i can use it as a generic function I can use to connect to any file I need to connect to - each would return different data (one could be user data, one could be complex calculations etc).
When it retrieves the data from PHP, is there a way to dynamically set the variables based on what is received - even if i do not know what has been received.
I can make PHP return to VBA the string in any format, so I'm using the below as an example:
String that is received in vba:
myValue1=Dave&someOtherValue=Hockey&HockeyDate=Yesterday
If i were to parse this in PHP, I could do something similar to (not accurate, just written for example purposes);
$myData = "myValue1=Dave&someOtherValue=Hockey&HockeyDate=Yesterday"
$myArr = explode("&",$myData)
foreach($myArr as $key => $value){
${$key} = $value;
}
echo $someOtherValue; //Would output to the screen 'Hockey';
I would like to do something similar in VBA. The string I am receiving is from a PHP file, so I can format it any way (json etc etc), I just essentially want to be able to define the VARIABLES when outputting the string from PHP. Is this possible in VBA?.
The current state of the function I have that is working great for connections is as below:-
Function kick_connect(url As String, formdata)
'On Error GoTo connectError
Dim http
Set http = CreateObject("MSXML2.XMLHTTP")
http.Open "POST", url, False
http.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
http.send (formdata)
kick_connect = http.responseText
Exit Function
connectError:
kick_connect = False
End Function
Ultimately, I want to be able to do something like
sub mySub
myData = "getId=" & Range("A1").Value
myValue = kick_connect("http://path-to-my-php-file.php",myData)
if myValue = False then
'Handle connection error here
exit sub
end if
'do something snazzy here to split "myValue" string (eg "myValue1=Dave&someOtherValue=Hockey&HockeyDate=Yesterday") into own variables
msgbox(myValue1) 'Should output "Dave"
end sub
Obviously I could put the values into an array, and reference that, however I specifically want to know if this exact thing is possible, to allow for flexibility with the scripts that already exist.
I hope this makes sense, and am really grateful for any replies i get.
Thank you.
You can use a Collection:
Dim Tmp As String
Dim s As String
Dim i As Integer
Dim colVariabili As New Collection
Tmp = "myValue1=Dave&someOtherValue=Hockey&HockeyDate=Yesterday"
Dim FieldStr() As String
Dim FieldSplitStr() As String
FieldStr = Split(Tmp, "&")
For Each xx In FieldStr
FieldSplitStr = Split(xx, "=")
colVariabili.Add FieldSplitStr(1), FieldSplitStr(0)
Next
Debug.Print colVariabili("myValue1")
Debug.Print colVariabili("someOtherValue")
Debug.Print colVariabili("HockeyDate")
It's ok if you don't have the correct sequence of var...
I am not sure if this can help you, but as far as I understand your question you want to be able to create the variables dynamically based on the query string parameters. If so then here is example how to add this variables dynamically. Code needs standard module with a name 'QueryStringVariables'. In this module the query string will be parsed and each query string parameter will be added as get-property. If you wish to be able to change the value as well then you will need to add let-property as well.
Add reference to Microsoft Visual Basic For Applications Extensibility
Option Explicit
Private Const SourceQueryString As String = "myValue1=Dave&someOtherValue=Hockey&HockeyDate=Yesterday"
Sub Test()
Dim queryStringVariablesComponent As VBIDE.vbComponent
Dim queryStringVariablesModule As VBIDE.CodeModule
Dim codeText As String
Dim lineNum As Long: lineNum = 1
Dim lineCount As Long
Set queryStringVariablesComponent = ThisWorkbook.VBProject.VBComponents("QueryStringVariables")
Set queryStringVariablesModule = queryStringVariablesComponent.CodeModule
queryStringVariablesModule.DeleteLines 1, queryStringVariablesModule.CountOfLines
Dim parts
parts = Split(SourceQueryString, "&")
Dim part, variableName, variableValue
For Each part In parts
variableName = Split(part, "=")(0)
variableValue = Split(part, "=")(1)
codeText = "Public Property Get " & variableName & "() As String"
queryStringVariablesModule.InsertLines lineNum, codeText
lineNum = lineNum + 1
codeText = variableName & " = """ & variableValue & ""
queryStringVariablesModule.InsertLines lineNum, codeText
lineNum = lineNum + 1
codeText = "End Property"
queryStringVariablesModule.InsertLines lineNum, codeText
lineNum = lineNum + 1
Next
DisplayIt
End Sub
Sub DisplayIt()
MsgBox myValue1 'Should output "Dave"
End Sub
I got a bit of a stupid question;
Currently I am making a website for a company on a server which actually has a bit an outdated PHP version (5.2.17). I have a database in which many fields are varchar with characters like 'é ä è ê' and so on, which I have to display in an HTML page.
So as the version of PHP is outdated (and I am not allowed to updated it because there are parts of the site that must keep working and to whom I have no acces to edit them) I can't use the htmlentities function with the ENT_SUBSTITUTE argument, because it was only added after version 5.4.
So my question is:
Does there exist an alternative to
htmlentities($string,ENT_SUBSTITUTE); or do I have to write a function
myself with all kinds of strange characters, which would be incomplete anyway.
Define a function for handling ill-formed byte sequences and call the function before passing the string to htmlentties. There are various way to define the function.
At first, try UConverter::transcode if you don't use Windows.
http://pecl.php.net/package/intl
If you are willing to handle bytes directly, see my previous answer.
https://stackoverflow.com/a/13695364/531320
The last option is to develop PHP extension. Thanks to php_next_utf8_char, it's not hard.
Here is code sample. The name "scrub" comes from Ruby 2.1 (see Equivalent of Iconv.conv("UTF-8//IGNORE",...) in Ruby 1.9.X?)
// header file
// PHP_FUNCTION(utf8_scrub);
#include "ext/standard/html.h"
#include "ext/standard/php_smart_str.h"
const zend_function_entry utf8_string_functions[] = {
PHP_FE(utf8_scrub, NULL)
PHP_FE_END
};
PHP_FUNCTION(utf8_scrub)
{
char *str = NULL;
int len, status;
size_t pos = 0, old_pos;
unsigned int code_point;
smart_str buf = {0};
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len) == FAILURE) {
return;
}
while (pos < len) {
old_pos = pos;
code_point = php_next_utf8_char((const unsigned char *) str, len, &pos, &status);
if (status == FAILURE) {
smart_str_appendl(&buf, "\xEF\xBF\xBD", 3);
} else {
smart_str_appendl(&buf, str + old_pos, pos - old_pos);
}
}
smart_str_0(&buf);
RETURN_STRINGL(buf.c, buf.len, 0);
smart_str_free(&buf);
}
You don't need ENT_SUBSTITUTE if your encoding is handled correctly.
If the characters in your database are utf-8, stored in utf-8, read in utf-8 and displayed to the user in utf-8 there should be no problem.
Just add
if (!defined('ENT_SUBSTITUTE')) define('ENT_SUBSTITUTE', 0);
and you'll be able to use ENT_SUBSTITUTE into htmlentities.
this is my first post and I'm very new with mysql and php.
I'm currently doing AES encryption for passwords.
I'm using this encryption: http://www.phpclasses.org/package/4238-PHP-Encrypt-and-decrypt-data-with-AES-in-pure-PHP.html since we don't have SSL security and must protect our server side as well.
It gives me an encrypted string like this : '�<�rB�5�]��MJ' and mysql fails at inserting the string even though I put the column type in unicode-general.
Can you help this poor damsel?
Thank you for your time.
<?php
$input = '123456';
function Encrypt($toEncrypt)
{
$Cipher = new AESCipher(AES::AES256);
$password = 'superKeyHere';
$cryptext = $Cipher->encrypt($toEncrypt, $password);
return CleanUpString($cryptext);
}
function Decrypt($toDecrypt)
{
$Cipher = new AESCipher(AES::AES256);
$password = 'superKeyHere';
$output = $Cipher->decrypt($toDecrypt, $password);
return CleanUpString($output);
}
function CleanUpString($inp)
{
return str_replace(array("�", "ۓ"), array("=^_^=", "=^.^="), $inp);
}
$cryptext=Encrypt($input) ;
//Encrypted
print 'cryptext: '.$cryptext.'<br />';
$oSql = new sql(0);
$cryptext=mysql_real_escape_string($cryptext);
$oSql->query("update userTab set pass='$cryptext' where id=1");
$oSql = new sql(0);
$oSql->query("select pass from userTab where id=1");
$rows = $oSql->get_table_hash();
$cryptext="";
if (sizeof($rows) >0){
$cryptext= $rows[0]["pass"];
}
$cryptext=Decrypt($cryptext);
//Decrypted
print 'message: '.$cryptext.'<br />';
?>
To store data that you encrypt, it is probably necessary to use some kind of BLOB field like VARBINARY. Otherwise, MySQL will try to validate the data, which almost certainly will not be valid Unicode data. Another possibility would be to convert the encrypted data to Base64 encoding. That data could then be stored in a Unicode (or even ANSI) field.
In your particular case I recommend BASE16-encoding the encrypted data (BASE-16 is when each character is replaced by it's hex code, with 20 being for " "/space, 41 being for "A" etc). This way you get alphanumeric string which can be safely inserted into the DB.
And even better approach is to not keep passwords in the database, instead keeping the salt (some unique value) and hash of (password+salt). This is much more secure from many aspects.
You could try the format Windows-1252. Maybe that works.