As a part of my JS code, using web crypto, I wanted to sign a string, serialize it and later desrialize it and verify it.
For this I created these custom functions createHexTokenFromStrClaim and verifyHexTokenAndGetStrClaim. However my code is not behaving as expected.
Minimal working code:
const keyUsages = ["sign","verify"];
const algo = {
name: "HMAC",
hash: {name: "SHA-512"}
};
class Util{
static text_encoder=new TextEncoder();
static text_decoder=new TextDecoder();
static characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
static hexEncode(str) {
let hex = '';
for (let i = 0; i < str.length; i++) {
let charCode = str.charCodeAt(i);
if (charCode < 128) {
hex += charCode.toString(16).padStart(2, '0');
} else if (charCode < 2048) {
hex += ((charCode >> 6) | 0xC0).toString(16).padStart(2, '0');
hex += ((charCode & 0x3F) | 0x80).toString(16).padStart(2, '0');
} else {
hex += ((charCode >> 12) | 0xE0).toString(16).padStart(2, '0');
hex += (((charCode >> 6) & 0x3F) | 0x80).toString(16).padStart(2, '0');
hex += ((charCode & 0x3F) | 0x80).toString(16).padStart(2, '0');
}
}
return hex;
}
static hexDecode(hex) {
let str = '';
for (let i = 0; i < hex.length; i += 2) {
const byte = parseInt(hex.substr(i, 2), 16);
str += String.fromCharCode(byte);
}
return decodeURIComponent(escape(str)); // Handle UTF-8 encoding
}
static async createHexTokenFromStrClaim(algo,str_claim,crypto_key){
const hex_str_claim= Util.hexEncode(str_claim);
const uint = Util.text_encoder.encode(hex_str_claim);
const ab = uint.buffer;
const sign = await crypto.subtle.sign(algo,crypto_key,ab);
const des = Util.text_decoder.decode(sign);
console.log(new Uint8Array(sign));
const hex_sign=Util.hexEncode(des);
return hex_str_claim+"."+hex_sign;
}
static async verifyHexTokenAndGetStrClaim(algo,hex_token,crypto_key){
let hex_str_claim,hex_sign;
[hex_str_claim,hex_sign]=hex_token.split(".");
if(hex_str_claim && hex_sign){
const uint = Util.text_encoder.encode(hex_str_claim);
const ab = uint.buffer;
const des = Util.hexDecode(hex_sign);
const sign = Util.text_encoder.encode(des);
console.log(sign);
const r = await crypto.subtle.verify(algo,crypto_key,sign.buffer,ab);
if(r){
return Util.hexDecode(hex_str_claim);
}
}
return;
}
}
(async()=>{
const crypto_key = await crypto.subtle.generateKey(algo,true,keyUsages);
const message = "Hello world こんにちは、元気ですか ईश्वरेण सह एकतां प्राप्तुं एषः महान् दिवसः अस्ति";
const token = await Util.createHexTokenFromStrClaim(algo,message,crypto_key);
console.log(token);
const claim = await Util.verifyHexTokenAndGetStrClaim(algo,token,crypto_key);
console.log(claim);
})();
Hex Enconder is used as encoding like base64 introduces special characters , which causes issues with other part of the code.
Problem:
Verification seems to be failing. Specially inverifyHexTokenAndGetStrClaim the sign is comming completely different after econding it using const sign = Util.text_encoder.encode(des);
Can’t figure out what I am doing wrong.
Have checked most of the resources about encoding and decoding.
Have checked most of the resource for signing and verifying.