So I am making my custom highscore board in mobile game, using unity engine.
I setup my mysql database, and bought highscore asset from store, it works, but only with english user name. So basically it send user's name, score to .php script.
But I want that script also can receive korean characters as user's nickname. My users will use korean characters too as nickname not only english characters.
How can I achieve this?
Here are codes.
------------------(Highscore.cs at unity side)
WWWForm rsFm = new WWWForm();
rsFm.AddField("name",name);
// at here name field, I want to receive korean characters as well.
rsFm.AddField("tables",tables);
rsFm.AddField("hash",GetHash(name));
WWW rs = new WWW(registerUserURL,rsFm);
yield return rs;
..................
string GetHash(string usedString){ //Create a Hash to send to server
MD5 md5 = MD5.Create();
byte[] bytes = Encoding.ASCII.GetBytes(usedString+secretKey);
byte[] hash = md5.ComputeHash(bytes);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < hash.Length; i++){
sb.Append(hash[i].ToString("x2"));
}
return sb.ToString();
}
RegisterUser.php
<?php
include('ServerConnect.php');
$connection = Connect();//Attempt to Connect to MYSQL Server & DataBase
//Get variables from unity
$name = $_POST['name'];
$date = strtotime(date("Y-m-d"));
$tables = $_POST['tables'];
//Security Check
$hash = $_POST['hash'];
if(CheckKey($hash,$name) == 'fail'){ //Check if hash is valid
echo 'Security Failure'; exit;
}
ServerConnect.php
function CheckKey($hash,$name){ //Check weather Md5 hash matches
global $secretKey;
$checkHash = md5($name.$secretKey);
if(strcmp($checkHash,$hash) == 0){
return 'pass'; //hash matches
}else{
return 'fail'; //hash failed
}
}
When I input korean character and send, console Result says "Security Failure" at above code.
like a user has stated before, you are using the wrong encoding if you will be using out of ascii chars (the case for korean, japanese, etc). You should be using Encoding.UTF8.GetBytes instead of Encoding.ASCII.GetBytes, take a look at https://msdn.microsoft.com/en-us/library/system.security.cryptography.md5%28v=vs.110%29.aspx for the example function GetMd5Hash. If you run ASCII md5, a different md5 will be generated.
The "salt" is the secret key you are using. $secretKey in PHP and secretKey in C#. You should read a little about security if you dont know what salt is, because if you dont you'll think you created a secure(r) system and you havent.
Hope it helps.
Related
I have an app in vb.net and I want to store a password in my database that is understandable from PHP. The creation in PHP is like this:
$hash = password_hash("mypassword", PASSWORD_BCRYPT);
The result looks like this:
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';
and the code in php to validate a password looks likethis
if (password_verify('mypassword', $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
How can I replicate this code
$hash = password_hash("mypassword", PASSWORD_BCRYPT);
iv VB.Net, so the results will match exactly?
In the php line, you provided, you use the bcrypt algorithm to hash the password.
This is a general hashing algorithm, not unique to php.
Im not very familar with VB.net, but this is what I found with a quick search:
' This example assumes the Chilkat API to have been previously unlocked.
' See Global Unlock Sample for sample code.
Dim crypt As New Chilkat.Crypt2
' The BCrypt cost factor (work factor) can be set to a value from 4 to 31.
' The default value is 10. We'll set it here explicitly to the default value
' to make this new property known. This line of code can be omitted
' if the default value of 10 is desired.
crypt.BCryptWorkFactor = 10
Dim bcryptHash As String = crypt.BCryptHash("mySecretPassword")
Debug.WriteLine("BCrypt hash = " & bcryptHash)
' Sample output:
' BCrypt hash = $2a$10$H5kIVktMGzAPKGKNAe9DVu0iwEqfhv/o4MMJ/Dzw/MPy1leOE9NOK
' Note: Your output will be different because the BCryptHash method
' automatically generates a random salt.
TrinityCore deprecated the old sha_pass_hash column on the auth table, in favour of the much safer SRP6 method. However, I am unable to properly calculate the verifier in C#/dotnet NOR in PHP using the example provided here. I've looked at examples but it doesn't seem to be working the way that the TrinityCore developers suggest. Does anyone know about SRP6 that might be able to figure out what's wrong in the code? I've also looked at this example but it uses a hardcoded salt? If someone can show me what's wrong in the PHP I might be able to figure out what's wrong with the .NET
The code I tried looks closest to the first example, but I flip my arrays around to be little-endian.
public byte[] CalculateVerifier(string username, string password, byte[] salt)
{
if (BitConverter.IsLittleEndian)
{
return BigInteger.ModPow(
g,
new BigInteger(Hash(salt, Hash(Encoding.UTF8.GetBytes($"{username.ToUpper()}:{password.ToUpper()}")))),
N
).ToByteArray();
}
else
{
return BigInteger.ModPow(
g,
new BigInteger(Hash(salt, Hash(Encoding.UTF8.GetBytes($"{username.ToUpper()}:{password.ToUpper()}")).Reverse().ToArray())),
N
).ToByteArray();
}
}
public bool VerifySRP6Login(string username, string password, byte[] salt, byte[] verifier)
{
// re-calculate the verifier using the provided username + password and the stored salt
byte[] checkVerifier = CalculateSRP6Verifier(username, password, salt);
Console.WriteLine($"{Encoding.ASCII.GetString(verifier)} {verifier.Length} bytes\n{Encoding.ASCII.GetString(checkVerifier)} {checkVerifier.Length} bytes");
Console.WriteLine($"{new BigInteger(verifier)}\n{new BigInteger(checkVerifier)}");
// compare it against the stored verifier
return verifier.SequenceEqual(checkVerifier);
}
public byte[] Hash(byte[] componentOne, byte[] componentTwo)
{
if (componentOne == null) throw new ArgumentNullException(nameof(componentOne));
if (componentTwo == null) throw new ArgumentNullException(nameof(componentTwo));
//WoW expects non-secure SHA1 hashing. SRP6 is deprecated too. We need to do it anyway
using (SHA1 shaProvider = SHA1.Create())
{
//See Jackpoz's Combine function
return shaProvider.ComputeHash(componentOne.Concat(componentTwo).ToArray());
}
}
public byte[] Hash(byte[] bytes)
{
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
//WoW expects non-secure SHA1 hashing. SRP6 is deprecated too. We need to do it anyway
using (SHA1 shaProvider = SHA1.Create())
{
return shaProvider.ComputeHash(bytes);
}
}
The answer was found in this solution, apparently I wasn't properly making my BigInteger, because the data was an unsigned int and I was treating it as signed.
I am using the SHA512 hash to transfer some encrypted data between my app and it's backend. However, I'm having a odd situation and have no idea what might be causing it.
So, I've got following setups tested:
Android 2x SHA512
Android 1x SHA512 -> CryptoJS 1x SHA512
PHP 2x SHA512
So, when I do the first 2x Android hashing, I get the same result as when I do the 1x android -> 1x cryptojs.
However, when I do the PHP 2x, I get the same result as I get on the first Android pass, but the second encryption pass of the PHP is different.
On PHP, I've tried both the hash() and openssl_digest() functions with raw bytes as output.
PHP:
$firstpass = base64_encode(hash('sha512', $enteredPassword, true));
//$firstpass = base64_encode(hash('sha512', $enteredPassword, true));
//$secondpass = base64_encode(openssl_digest($firstpass, 'sha512', true));
$secondpass = base64_encode(hash('sha512', $firstpass, true));
Android:
public static String encryptPassword(String password) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("SHA-512");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
if (md != null) {
md.update(password.getBytes());
byte byteData[] = md.digest();
String base64 = Base64.encodeToString(byteData, Base64.DEFAULT);
return base64;
}
return password;
}
CryptoJS:
var password = cryptojs.SHA512(req.params.password);
var basepassword = password.toString(cryptojs.enc.Base64);
Why would my first hash be correct and my second not and how could I fix this?
SHA1 is not made for security, don't use it for this.
Grab any implementation of BCrypt and do security right.
As for the different hashes: Most likely an encoding issue related to Strings.
I have a problem (server side) when i encrypt data from a client and i send to webserver with Post Method.
i Use this Method to Encrypt from a C# Client
public string Encrypt3DES(string strString)
{
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Key = Encoding.GetBytes(this.Key);
DES.Mode = CipherMode.ECB;
DES.Padding = PaddingMode.Zeros;
ICryptoTransform DESEncrypt = DES.CreateEncryptor();
byte[] Buffer = encoding.GetBytes(strString);
return Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
}
When i send ecrypted String to PHP if there was a + in that string, php read it with a blank space. If instead there'isnt any '+' i haven't any problem.
For Example this is a Encrypted String 4aY+na42iaPg+aep== in C# when i read in php it's
4aY a42iaPg aep== so if i decrypt if dont match with the correct word.
i use this script to start read method post
if (isset($_POST['doConvalid'])){
if ($_POST['doConvalid']=='Convalid')
{
foreach($_POST as $keys => $values) {
$data[$keys] =($values); // post variables are filtered
}
$cheking=$data['check'];
echo("Show checking = $checking"); //Here i read string with blank space instead +
Is there a way to fix it?
Yes base64 decodes + to space use this:
echo str_replace(" ","+",$_POST['string']);
http://en.wikipedia.org/wiki/Base64#URL_applications
You could replace the '+' with a different character (something not used by base64) for sending. Then replace that character back to '+' for decoding.
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.