96 lines
2.9 KiB
TypeScript
96 lines
2.9 KiB
TypeScript
import { S3Client, GetObjectCommand, HeadObjectCommand } from "@aws-sdk/client-s3";
|
|
|
|
const s3Ledger = new S3Client({
|
|
region: process.env.AWS_REGION || "eu-west-3",
|
|
credentials: {
|
|
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
|
|
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
|
|
},
|
|
});
|
|
|
|
export interface LedgerIntegrityResult {
|
|
valid: boolean;
|
|
hash_match: boolean;
|
|
compliance_locked: boolean;
|
|
locked_until: Date | null;
|
|
version_id: string | null;
|
|
error?: string;
|
|
}
|
|
|
|
/**
|
|
* Vérifie l'intégrité d'une vérification de signature avec le ledger S3 immuable
|
|
*/
|
|
export async function verifyLedgerIntegrity(
|
|
verificationData: {
|
|
id: string;
|
|
signature_hash: string;
|
|
s3_ledger_key: string;
|
|
signer_email: string;
|
|
}
|
|
): Promise<LedgerIntegrityResult> {
|
|
try {
|
|
// 1. Récupérer le document depuis S3
|
|
const getCommand = new GetObjectCommand({
|
|
Bucket: "odentas-signatures-ledger",
|
|
Key: verificationData.s3_ledger_key,
|
|
});
|
|
|
|
const s3Response = await s3Ledger.send(getCommand);
|
|
const ledgerData = JSON.parse(await s3Response.Body!.transformToString());
|
|
|
|
// 2. Vérifier que les données correspondent
|
|
const hashMatch = ledgerData.signature.hash === verificationData.signature_hash;
|
|
const idMatch = ledgerData.verification_id === verificationData.id;
|
|
const emailMatch = ledgerData.signer.email === verificationData.signer_email;
|
|
|
|
// 3. Vérifier l'Object Lock
|
|
const headCommand = new HeadObjectCommand({
|
|
Bucket: "odentas-signatures-ledger",
|
|
Key: verificationData.s3_ledger_key,
|
|
});
|
|
|
|
const headResponse = await s3Ledger.send(headCommand);
|
|
|
|
const isComplianceLocked = headResponse.ObjectLockMode === "COMPLIANCE";
|
|
const lockDate = headResponse.ObjectLockRetainUntilDate
|
|
? new Date(headResponse.ObjectLockRetainUntilDate)
|
|
: null;
|
|
const lockValid = lockDate ? lockDate > new Date() : false;
|
|
|
|
return {
|
|
valid: hashMatch && idMatch && emailMatch && isComplianceLocked && lockValid,
|
|
hash_match: hashMatch,
|
|
compliance_locked: isComplianceLocked,
|
|
locked_until: lockDate,
|
|
version_id: headResponse.VersionId || null,
|
|
};
|
|
} catch (error) {
|
|
console.error("Erreur vérification ledger:", error);
|
|
return {
|
|
valid: false,
|
|
hash_match: false,
|
|
compliance_locked: false,
|
|
locked_until: null,
|
|
version_id: null,
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère le document complet depuis le ledger S3
|
|
*/
|
|
export async function getLedgerDocument(s3Key: string) {
|
|
try {
|
|
const command = new GetObjectCommand({
|
|
Bucket: "odentas-signatures-ledger",
|
|
Key: s3Key,
|
|
});
|
|
|
|
const response = await s3Ledger.send(command);
|
|
return JSON.parse(await response.Body!.transformToString());
|
|
} catch (error) {
|
|
console.error("Erreur récupération ledger:", error);
|
|
throw error;
|
|
}
|
|
}
|