export interface AssertionData { idpEntityId: string; subjectId: string; sessionId: string; now: string; expire: string; spEntityId: string; } export async function encodeAssertion( key: CryptoKey, assertionData: AssertionData, ): Promise { return btoa(await signAssertion(key, assertionData)); } async function signAssertion( key: CryptoKey, assertionData: AssertionData, ): Promise { const digest = await digestValue(assertionData); const signature = await signatureValue(key, assertionData); return signedAssertion(assertionData, digest, signature); } function signedAssertion( assertionData: AssertionData, digest: string, signature: string, ): string { return `${digest}${signature}${assertionData.idpEntityId}${assertionData.subjectId}${assertionData.spEntityId}`; } async function signatureValue( key: CryptoKey, assertionData: AssertionData, ): Promise { const digest = await digestValue(assertionData); const enc = new TextEncoder(); console.log("signature part"); console.log(signaturePart(digest)); const signatureData = await crypto.subtle.sign( "RSASSA-PKCS1-v1_5", key, enc.encode(signaturePart(digest)), ); return arrayBufferToBase64(signatureData); } function signaturePart(digest: string): string { return `${digest}`; } async function digestValue(assertionData: AssertionData): Promise { const enc = new TextEncoder(); console.log("digest part"); console.log(digestPart(assertionData)); const digestData = await crypto.subtle.digest( "SHA-256", enc.encode(digestPart(assertionData)), ); return arrayBufferToBase64(digestData); } function digestPart(assertionData: AssertionData): string { return `${assertionData.idpEntityId}${assertionData.subjectId}${assertionData.spEntityId}`; } function arrayBufferToBase64(buffer: ArrayBuffer): string { const bytes = new Uint8Array(buffer); const len = bytes.byteLength; let binary = ""; for (let i = 0; i < len; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary); }