Saving a hashed string in Salesforce? - hash

Not a SFDC expert but need to integrate a web form hosted in SFDC. For other reasons, this page needs to capture an initial password and send off the salted/sha256'd version of the password to another system or a human. I don't want to save the cleartext obviously.
What's the lightest touch way to hash the password before saving? I could do this in the browser except that I don't want to rely on Javascript.

Yes, you should add this code to an apex trigger.
trigger on sObject(before insert){
for(sObject s: trigger.new){
s.Hash__c = Crypto.generateDigest('SHA-256', Blob.valueOf(s.passwordString__c));
s.passwordString__c = null;
}
}

Here is the code to encrypt a string to SHA256 hash format :
//value to process
Blob data= Blob.valueOf('Any String');
or in case of field value
Blob data= Blob.valueOf(sObject.FieldAPIName));
Blob hash = Crypto.generateDigest('SHA-256', data);
//Convert SHA-256 Hash data to String
String encryptedString =EncodingUtil.convertToHex(hash);

Apex has a Crypto class which has a generateDigest method you need, something like:
Blob hash = Crypto.generateDigest('SHA-256', Blob.valueOf(passwordString));

This worked for me =>
String abc = EncodingUtil.convertToHex(
Crypto.generateDigest('SHA-256',
Blob.valueOf('test String')));

Related

How to upload file to mongodb on mongoose using nestJS?

Hello pls do somebody know how to upload file to MongoDB (mongoose) using nestJS ??
I already have the ability to #Post upload file to my nestJS projet and #Get, but know I wanna post to mongodb using mongoose, pls help
I don't recommend to store images on your database but you can do this:
async function saveFile(file: Express.Multer.File){
//Convert the file to base64 string
const fileB64 = file.buffer.toString('base64')
//userModel is a mongoose model
//Store the string
await this.userModel.create({file: fileB64})
}
async function getFile(userId: string){
//Get user from database
const user = await this.userModel.findOne({_id: userId}).lean()
if(!user) throw new NotFoundException('User not found')
const file = user.file
//Convert the string to buffer
return Buffer.from(file, 'base64')
}
First you have to convert that file to a string with base64 encoding then you can save that string on your database with the create method or updating a document.
If you want to get that file just search that info in your database and then convert the string to buffer and return it.
Like I said before, I don't recommend this it is better if you upload the buffer to s3 and save the link on your database.
thanks it is worked, but it is only buffer a can't see the image! please is there any others option to get is as image? please here what i'm getting :
{"type":"Buffer","data":[255,216,255,224,0,16,74,70,73,70,0,1,1,0,0,72,0,72,0,0,255,225,0,120,69,120,105,102,0,0,73,73,42,0,8,0,0,0,4,0,18,1,3,0,1,0,0,0,1,0,0,0,49,1,2,0,7,0,0,0,62,0,0,0,18,2,3,0,2,0,0,0,2,0,2,0,105,135,4,0,1,0,0,0,70,0,0,0,0,0,0,0,71,111,111,103,108,101,0,0,3,0,0,144,7,0,4,0,0,0,48,50,50,48,2,160,4,0,1,0,0,0,208,2,0,0,3,160,4,0,1,0,0,0,0,5,0,0,0,0,0,0,255,192,0,17,8,5,0,2,208,3,1,34,0,2,17,1,3,17,1,255,196,0,31,0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,16,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125,1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193....
Angular service file
postFile(fileToUpload: File): Observable<any> {
const formaData: FormData = new FormData();
formaData.append('fileKey', fileToUpload, fileToUpload.name);
return this.http.post(`${this.backEndURL}/api/prods/upload/two/tree/`, JSON.stringify(formaData));}
but my backend Nestjs trow error:
[ExceptionsHandler] Cannot read property 'buffer' of undefined +80859ms
TypeError: Cannot read property 'buffer' of undefined

How to make Webapi GET method work with reserved characters on query param?

I have a very simple webservice with one GET method that has a token string parameter. I use this token can have letters, "+" and "/". Ex.: mC1SW7RJhgsQGtRHhsg/Q+FGoZjbBleNKtpqT7zLMtE
I use this token to look in the database if there is data for this token.
My method in the controller is like that:
[HttpGet("{token}")]
[ProducesResponseType(typeof(string), 200)]
[ProducesResponseType(typeof(void), 404)]
public JsonResult Get(string token)
{
string sql = "SELECT dataObject FROM Session WHERE id = #SessionToken";
var data = _conn.QueryFirstOrDefault<Session>(sql, new {SessionToken = token});
if (data == null){
var r = Json(string.Empty);
r.StatusCode = StatusCodes.Status404NotFound;
return r;
}
else {
return Json(JsonConvert.DeserializeObject(data.dataObject));
}
}
I see Dapper/Webapi automatically escapes this parameter and change "/" to "%2F" for example.
When I deploy it just works for tokens without special characters and return 404.
As a workaround I changed the token in the server to encode the token and replace the encoded plus sign to space:
string decodedToken = WebUtility.UrlDecode(token);
token = decodedToken.Replace(" ", "+");
The problem is that I need my clients to do the inverse and replace the '+' sign:
var encodedToken = WebUtility.UrlEncode(token);
// Convert '+' to ' '
token = encodedToken.Replace("%2B", " ");
What is the recommended way to work without asking the client to replace de '+' signs?
For some reason Kestrel or .NET MVC do a partial decode in a encoded URL. This looks like a BUG (https://github.com/aspnet/Mvc/issues/6388), but there is a workaround.
With the token you passed in question you would encode it in the client:
Original Token: mC1SW7RJhgsQGtRHhsg/Q+FGoZjbBleNKtpqT7zLMtE
Encoded Token: mC1SW7RJhgsQGtRHhsg%2FQ%2BFGoZjbBleNKtpqT7zLMtE
See that '/' became '%2F' and '+' became '%2B'. This is because these two characters are part of the composition of a URL. Therefore to pass them fully to WebApi they must be replaced with their ASCII representation.
You would call your service with the encoded token like this:
http://myserver:1234/myservice/token/mC1SW7RJhgsQGtRHhsg%2FQ%2BFGoZjbBleNKtpqT7zLMtE
In your service, because of the bug, you would receive from Kestrel/MVC the following string partially decoded:
Partially decoded token: mC1SW7RJhgsQGtRHhsg%2FQ+FGoZjbBleNKtpqT7zLMtE
Just implement a simple replace:
token.Replace("%2F", "/");
And your string will be full decoded.
Try to add below code in your web.config:
<system.webServer>
<security>
<requestFiltering allowDoubleEscaping="true" />
</security>
</system.webServer>
Refer to Dotnet core + (plus) sign in Web API routing

How to compare two passwords in codeigniter using encryption

I stored a password in database using an encryption key, but now, when the user wants to login in the system, how can I compare both passwords? Each time it gives a different encrypted password..
$first_password = $this->input->post('password');
$password=$this->encrypt->encode($first_password);
Here is my model code
public function validate_login($username,$password){
$q = $this->db->where(['username'=>$username,'password'=>$password])
->get('oss_user');
if($q->num_rows()){
return $q->row()->user_id;
}
else{
return FALSE;
}
My question is: how can I compare the user entered password with the password stored in database?
You can not compare encrypted password this way. First you have get record from database using email id, once you find row of same email id then you have to pass encrypted password which is store in database on this function "$this->encrypt->decode($encrypted_password);", so you get back original password from encryption form and then compare it with password given during login session, please see follow code.
public function validate_login($username,$password){
$q = $this->db->where(['username'=>$username])
->get('oss_user');
if($q->num_rows()){
$desc_password = $this->encrypt->decode($q->row()->password);
if($desc_password == $password){
return $q->row()->user_id;
}
else
return FALSE;
}
else{
return FALSE;
}

Google Cloud Services put Fails when Using Signed URL

I am not able to PUT a file to google cloud services via a signed URL. When I try to do a PUT from a JS Client, I get:
"SignatureDoesNotMatch...The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method."
When I try to post the file using CURL, I get the same error.
The curl command I use is:
#!/bin/bash
URL="https://storage.googleapis.com/..."
echo $URL
curl $URL -H "Content-Type: image/jpg" --upload-file b.jpg
I have configured the bucket I intend to post data to based on the documentation, I have generated a service account with the key, and this key is used to generate the signed url.
The request I sign is of the form:
PUT
image/jpg
1234567890
my-bucket/b.jpg
where the expiration and bucket names are set and computed.
I have the following Groovy code to generate signed urls:
public String sign(PrivateKey key, String toSign) {
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initSign(key);
signer.update(toSign.getBytes("UTF-8"));
byte[] rawSignature = signer.sign();
String s = new String(Base64.encodeBase64(rawSignature), "UTF-8");
return s;
}
public String signUrl(PrivateKey key, String clientId, String method, String md5, String contentType,
long expiration, String gcsPath) {
String toSign = "${method}\n${md5}\n${contentType}\n${expiration}\n${gcsPath}";
String signature = sign(key, toSign);
String url = java.net.URLEncoder.encode(signature);
return url;
}
public String generateSignedUrl(PrivateKey key, String clientId, String method, String md5, String contentType,
long expiration, String gcsPath) {
String canonicalizedResource = "/${gcsPath}";
String signature = signUrl(key, clientId, method, md5, contentType, expiration, canonicalizedResource);
String finalUrl = "https://storage.googleapis.com/${gcsPath}?GoogleAccessId=${clientId}&Expires=${expiration}&Signature=${signature}"
finalUrl
}
This code is accompanied with the following passing unit test lifted straight out of the gsutils github project (https://github.com/GoogleCloudPlatform/gsutil/blob/master/gslib/tests/test_signurl.py):
#Test
void thatWeCanSignAPutUrlCorrectly() {
String expected = """https://storage.googleapis.com/test/test.txt?GoogleAccessId=test#developer.gserviceaccount.com&Expires=1391816302&Signature=A6QbgTA8cXZCtjy2xCr401bdi0e7zChTBQ6BX61L7AfytTGEQDMD%2BbvOQKjX7%2FsEh77cmzcSxOEKqTLUDbbkPgPqW3j8sGPSRX9VM58bgj1vt9yU8cRKoegFHXAqsATx2G5rc%2FvEliFp9UWMfVj5TaukqlBAVuzZWlyx0aQa9tCKXRtC9YcxORxG41RfiowA2kd8XBTQt4M9XTzpVyr5rVMzfr2LvtGf9UAJvlt8p6T6nThl2vy9%2FwBoPcMFaOWQcGTagwjyKWDcI1vQPIFQLGftAcv3QnGZxZTtg8pZW%2FIxRJrBhfFfcAc62hDKyaU2YssSMy%2FjUJynWx3TIiJjhg%3D%3D""";
long expiration = 1391816302;
String signedUrl = gsUtils.generateSignedUrl(privateKey, "test#developer.gserviceaccount.com","PUT", "", "", expiration, "test/test.txt")
assertEquals(expected, signedUrl);
}
Thank you for whatever insights you may be able to provide, I have been at this problem for a while.
Debugging signed URL logic is difficult. There is a useful trick that helps, though. An error response like the one you describe will look like this:
<?xml version='1.0' encoding='UTF-8'?><Error><Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message>
<StringToSign>PUT
text/jpeg
1472720161
/myBucket/test.txt</StringToSign></Error>
That last bit, <StringToSign>, is critical. The string in there is exactly the string that GCS will sign, and it's the string that you should also be signing. Compare you string against this one; it will probably be different in some way.
Also, because implementing this signing logic is tricky, the gcloud-java library has a signUrl() method that I recommend you use instead of implementing the logic yourself.
One reason that might cause this error (happened to me before) is when you generate a base64 encoded signature with your signed string, the encoded signature may contain illegal url characters + and /. Make sure you replace them in the string with %2B and %2F, respectively.

Send a form with a hashed password

I need to submit a form with a "hash" function for the password. The question is, how can I change the initial value of the password textbox by the hashed value to insert in a DB?
I´m understanding the following. When I click the submit button, the form sends the values of textboxes to a php file. Particularly, as I said before, what I need is to send the new hashed password instead of original value.
I´m sorry if I´m not very clear but I´m very raw on this.
Thank you in advance
Part of the code I am using is the next:
...
<input type="password" id="upwd" name="upwd" onChange="validatePassword()">
<input id="submit" type="submit" value="Sign up!" onsubmit="sending()">
...
<script>
...
function sending () {
z = document.getElementById("upwd").value;
upwd = hashCode();
}
function hashCode() {
var hash = 0;
if (z.length === 0) return hash;
for (var i = 0; i < z.length; i++) {
var character = z.charCodeAt(i);
hash = ((hash<<5)-hash)+character;
hash &= hash; // Convert to 32bit integer
}
return hash;
}
</script>
Password hashing is done server side, in your case in the PHP script. You can use the PHP function password_hash() to calculate a safe BCrypt hash.
If you calculate the hash client side, a ManInTheMiddle will see the password hash, and could use it directly to get access to the user account. The hash would become the actual password.
Password hashing is done for the case that an attacker has read access to your database. In this case he would see the hashes, but would still not know the real passwords. Without the real password he cannot use the user account.