I want to query a table in oracle nosql cloud. I don't want to use any packages and want to use web crypto for creating the authorization header. I am trying to use the code below. But it is not working. What is the error here?
const oracleAuth = {}
oracleAuth.createHeaders = async function (httpMethod, host, requestPath, headers, body, privateKeyPem, tenancyOCID, userOCID, keyFingerprint) {
// Helper function to encode data in Base64
const base64Encode = (arrayBuffer) => {
let binary = '';
const bytes = new Uint8Array(arrayBuffer);
for (let i = 0; i \< bytes.byteLength; i++) {
binary += String.fromCharCode(bytes\[i\]);
}
return btoa(binary);
};
// Helper function to generate the signing string
const generateSigningString = (headersToSign, headers, requestTarget) => {
return headersToSign.map(header => {
if (header.toLowerCase() === '(request-target)') {
return \`(request-target): ${requestTarget}\`;
} else {
return \`${header.toLowerCase()}: ${headers\[header.toLowerCase()\]}\`;
}
}).join('\\n');
};
// Import the private key
const importPrivateKey = async (pem) => {
const pemHeader = '-----BEGIN PRIVATE KEY-----';
const pemFooter = '-----END PRIVATE KEY-----';
const pemHeaderStart = pem.indexOf(pemHeader);
const pemFooterStart = pem.indexOf(pemFooter);
const pemContents = pem.substring(pemHeaderStart + pemHeader.length, pemFooterStart).replace(/\\s+/g, '');
const binaryDerString = atob(pemContents);
const binaryDer = new Uint8Array(binaryDerString.length);
for (let i = 0; i \< binaryDerString.length; i++) {
binaryDer\[i\] = binaryDerString.charCodeAt(i);
}
return await crypto.subtle.importKey(
'pkcs8',
binaryDer.buffer,
{
name: 'RSASSA-PKCS1-v1\_5',
hash: 'SHA-256',
},
false,
\['sign'\]
);
};
// Compute the SHA-256 hash of the request body
const computeSHA256 = async (data) => {
const encoder = new TextEncoder();
const dataBuffer = encoder.encode(data);
const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);
return base64Encode(hashBuffer);
};
// Ensure headers keys are in lowercase
headers = Object.keys(headers).reduce((acc, key) => {
acc\[key.toLowerCase()\] = headers\[key\];
return acc;
}, {});
// Prepare headers
headers\['host'\] = host;
headers\['date'\] = new Date().toUTCString();
if (body) {
headers\['x-content-sha256'\] = await computeSHA256(body);
headers\['content-length'\] = body.length.toString();
headers\['content-type'\] = 'application/json';
} else {
headers\['x-content-sha256'\] = await computeSHA256('');
headers\['content-length'\] = '0';
headers\['content-type'\] = 'application/json';
}
// Define the headers to sign
const headersToSign = \['date', '(request-target)', 'host', 'content-length', 'content-type', 'x-content-sha256'\];
// Generate the signing string
const requestTarget = \`${httpMethod.toLowerCase()} ${requestPath}\`;
const signingString = generateSigningString(headersToSign, headers, requestTarget);
debugger
// Import the private key
const privateKey = await importPrivateKey(privateKeyPem);
// Sign the signing string
const encoder = new TextEncoder();
const signingStringBuffer = encoder.encode(signingString);
const signatureBuffer = await crypto.subtle.sign(
{
name: 'RSASSA-PKCS1-v1\_5',
hash: 'SHA-256',
},
privateKey,
signingStringBuffer
);
const signature = base64Encode(signatureBuffer);
// Construct the Authorization header
const keyId = \`${tenancyOCID}/${userOCID}/${keyFingerprint}\`;
const authorizationHeader = \`Signature version="1",headers="${headersToSign.join(' ')}",keyId="${keyId}",algorithm="rsa-sha256",signature="${signature}"\`;
const headersRet = {
'date': headers\['date'\],
'authorization': authorizationHeader,
'content-type': 'application/json',
'x-content-sha256': headers\['x-content-sha256'\],
'content-length': headers\['content-length'\],
}
return headersRet;
}
oracleAuth.test = async function () {
const httpMethod = 'POST';
const requestPath = 'https://nosql.ap-hyderabad-1.oci.oraclecloud.com/20190828/query';
const headers = {};
const body = JSON.stringify(
{
statement: "SELECT \* FROM otb1",
compartmentId: 'comp1'
}
)//
const hR\_priK = await fetch('./keys/pri.pem')
const privateKeyPem = await hR\_priK.text()
const tenancyOCID = \`ocid1.tenancy.oc1..XXX\`;
const userOCID = 'ocid1.user.oc1..xxx';
const keyFingerprint = '50:87:b5:93:6f:fb:05:e4:dc:a9:ec:a3:5f:3a:1c:ff';
const host = 'nosql.ap-hyderabad-1.oci.oraclecloud.com';
const er = await oracleAuth.createAuthorizationHeader(httpMethod, host, requestPath, headers, body, privateKeyPem, tenancyOCID, userOCID, keyFingerprint)
const hR = await fetch(requestPath, {
method: httpMethod,
headers: er,
body: body,
});
const txtR = await hR.text()
//error : "{"code":"InvalidAuthorization","message":"NotAuthenticated. The request signature is invalid, credentials information might be incorrect or public key is not ready to use"}"
}