I am working on a project in which API request & responses are sent after PGP encryption and then Base64 encoding. Similarly, after receiving the request, I have to first decode it with base64 & then PGP decryption is performed.
Whenever I use my own function in .Net to decode the request, PGP decryption gives error of illegal characters or unknown message format. But when I decode the request from an online tool that is https://www.base64decode.org , my PGP decryptor works fine.
I am using DidiSoft.PGP library for PGP encryption/decryption. Below is the code snippet I am using for Base64 decoding:
public static string Base64Decode(string base64EncodedData)
{
//Base64 URL Decode
string converted = base64EncodedData
.Replace('-', '+')
.Replace('_', '/')
.Replace(#"\/", "/");
byte[] base64EncodedBytes = Convert.FromBase64String(converted);
return Encoding.UTF8.GetString(base64EncodedBytes);
}
I wonder what algorithm is used in the online tool, or what I am missing to get the correct string. Any help is appreciated.
EDIT: One additional info I found out that I need to perform Base64 decoding according to RFC4648 Section 5 (RFC 4648 §5: base64url (URL- and filename-safe standard)). Can anyone pls. guide its implementation in .NetCore or is there any NugetPackage to do so
Related
I am working with Docusign connect and planning to use HMAC keys to authenticate the messages. I am referring https://developers.docusign.com/esign-rest-api/guides/connect-hmac#example-hmac-workflow link.
I find few terms confusing in the documentation. Attaching the code snippet from the doc for python.
def ComputeHash(secret, payload):
import hmac
import hashlib
import base64
hashBytes = hmac.new(secret, msg=payload, digestmod=hashlib.sha256).digest()
base64Hash = base64.b64encode(hashBytes)
return base64Hash;
def HashIsValid(secret, payload, verify):
return verify == ComputeHash(secret,payload)
Can you explain what payload(didn't understand exactly what it is), secret (I am guessing the secret key) and verify means from the above code and how do I verify my secret key with X-Docusign-Signature-1 which I get from response header?
My code:
message = request.headers
hashBytes = hmac.new(secret_key.encode('utf-8'), msg=message.encode('utf-8'), digestmod=hashlib.sha256).hexdigest()
base64Hash = base64.b64encode(hashBytes)
[Edited]
I found the solution on my own. Please read the first answer. I have explained it in details.
Sorry for the confusion.
Payload is "The entire body of the POST request is used, including line endings."
This is what you're encoding here using a Hash (HMAC) function.
SHA256 HMAC digest take in an the array of bytes (payload) and a secret (some key to use for encryption) and produces some encrypted version of the payload that can later be verified.
I highly recommend you ensure you first understand how the Connect webhook works without using HAMC encoding. This feature is meant to secure your application and it's a bit more complex. If you first get it working without it - you'll get a better grasp of what's going on (as well as feel a bit better about accomplishing a subtask).
Once you have it working, you can add the HMAC to make it secure and it will be easier at that point.
I found the solution to my problem.
expected_signature = request.headers['X-Docusign-Signature-1']
message = request.data # It is already in bytes. No need to encode it again.
hashBytes = hmac.new(secret_key.encode('utf-8'), msg=message, digestmod=hashlib.sha256).hexdigest()
actual_signature = base64.b64encode(hashBytes)
hmac.compare_digest(actual_signature.decode('utf-8'),expected_signature):
I'm trying to send email and password to API. The password needs to be encrypted with sha256.
So far I tried 2 packages - flutter_string_encryption and crypto but can't get it to work. With the first package, I can't find the sha256 method and with the second package, I'm getting an error when decoding List<Int> into a String. What is the proper way to do this?
The crypto documentation is straight forward. You can perform sha256 hashing as follows. If it doesn't solve what you are looking for, please add a minimum code that can reproduce the problem you are facing.
// import the packages
import 'package:crypto/crypto.dart';
import 'dart:convert'; // for the utf8.encode method
// then hash the string
var bytes = utf8.encode("foobar"); // data being hashed
var digest = sha256.convert(bytes);
print("Digest as hex string: $digest");
I'm setting up an Express.js endpoint that would support decoding a base64 string that came from the client (camera record), which is basically an encoded webm video.
The problem is that to validate this, I am trying to create a .webm video file from the encoded base64 string on the server. Unfortunately this results in a video file that cannot be played due to an error of "No video with supported format and MIME type found" (Ubuntu 18.04).
I did not have any issue with any other .webm files but also the base64 URL is sure to be correct as I am using it on the cliet as the source of a element to replay what was recorded and works fine.
The issue I suspect is something wrong with the code that generates the file on the server route.
import express from "express";
import multer from "multer";
import fs from "fs";
const router = express.Router();
// ...
router.post("/upload", multer().fields([]), (req, res) => {
const formData = req.body;
// formData.vid_string is the base64 encoded string
fs.writeFileSync(
"./test.webm",
Buffer.from(formData.vid_string.split(",")[1], "base64")
);
res.sendStatus(200);
});
I have also tried to change fs.writeFileSync code and add "base64" as a third argument but it has the same result.
Any input would be appreciated! Thanks!
I am pretty sure the correct way to do this is to remove the portion of the base64 string that is the URL specifications (If this is applicable to your situation being the part string that states base64 data and the "video/webm" portion and the trailing comma,) and call atob() on the resulting string this atob will represent the binary string version of the video. Then simply write that string to your new file!
However, I would recommend parsing the base64URL to binary string from the client side, since I am fairly sure that base64 uses more space to account for a smaller group of available bytes, if you have any control over how the video will be sent to the node server.
I'm trying to make a simple messaging app. I've encoded the strings in UTF-8 in Android through the provided methods:
String msg = "helloo";
byte[] bytemsg = msg.getBytes("UTF-8");
I'm sending this through MQTT (Paho library) to my server where I receive it using mosca library.
var received = new Buffer(payload).toString('utf8');
However, I'm not receiving what I sent. In the above example, I get ��� Also, when I send "hello", nothing gets displayed.
I read about javascript's problem with utf-8 characters, but I'm not using characters beyond the basic plane. I'd appreciate any help.
Get UTF-8 string from array of bytes
var buff = new Buffer(bytes);
console.log(buff.toString('utf8'));
I am using NodeJS's bundled crypto module for SHA256 hashing on the server-side.
On the client-side, I am using a javascript library called Crypto-JS.
I am using SHA256 hashes for a login system that uses classical nonce-based authentication. However, my server-side and client-side hash-digests don't match up even when the hash-messages are the same (I have checked this). Even the length of the hash-digests are different.
This is a snippet of my client-side implementation:
var password_hash = CryptoJS.SHA256( token.nonce /*this is the server's nonce*/ + cnonce + password ).toString(CryptoJS.enc.Base64);
This is a snippet of my server-side implementation:
var sha256 = CRYPTO.createHash("sha256");
sha256.update(snonce+cnonce+password, "utf-8");
var hash = sha256.digest("base64");
This is some sample data:
client-digest: d30ab96e65d09543d7b97d7cad6b6cf65f852f5dd62c256595a7540c3597eec4
server-digest: vZaCi0mCDufqFUwVO40CtKIW7GS4h+XUhTUWxVhu0HQ=
client-message: O1xxQAi2Y7RVHCgXoX8+AmWlftjSfsrA/yFxMaGCi38ZPWbUZBhkVDc5eadCHszzbcOdgdEZ6be+AZBsWst+Zw==b3f23812448e7e8876e35a291d633861713321fe15b18c71f0d54abb899005c9princeofnigeria
server-message: O1xxQAi2Y7RVHCgXoX8+AmWlftjSfsrA/yFxMaGCi38ZPWbUZBhkVDc5eadCHszzbcOdgdEZ6be+AZBsWst+Zw==b3f23812448e7e8876e35a291d633861713321fe15b18c71f0d54abb899005c9princeofnigeria
Does anyone know why the hashes are different? I thought that if it is the same protocol/algorithm, it will always produce the same hash.
Edit: Wow. I went to this online hashing tool and it produces yet another digest for the same message:
4509a6d5028b217585adf41e7d49f0e7c1629c59c29ce98ef7fbb96c6f27502c
Edit Edit: On second thought, the reason for the online hashing tool being different is probably because it uses a hex encoding and I used base64
The problem was indeed with encodings.
Look at the client-side implementation:
var password_hash = CryptoJS.SHA256(message).toString(CryptoJS.enc.Base64);
The CryptoJS.enc.Base64 parameter actually requires another component in the CryptoJS library that I did not include (stored in a js file: enc-base64-min.js). So, in the absence of a valid encoding type, it defaulted to hex.
Thanks #dhj for pointing out the encoding issue!
The problem is that your client produces hex-encoded digest, while server uses base64 encoding.