test(09-05): add failing convertCert spec (RED)
- PEM→DER round-trip identity test (re-parses DER base64 → verify CN) - DER→PEM round-trip identity test (re-parses PEM base64 → verify CN) - PEM→P7B: asserts mimeType + P7B contains ≥1 cert - malformed input: expects BadRequestException - All 4 fail against NotImplementedException stub (RED confirmed)
This commit is contained in:
@@ -322,3 +322,90 @@ describe('splitCerts', () => {
|
|||||||
).rejects.toThrow(BadRequestException);
|
).rejects.toThrow(BadRequestException);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// convertCert — RED tests (CERT-04)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
describe('convertCert', () => {
|
||||||
|
let service: CertManagerService;
|
||||||
|
let certPem: string;
|
||||||
|
let certDerBuffer: Buffer;
|
||||||
|
const CN = 'convert.example.com';
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
service = new CertManagerService();
|
||||||
|
|
||||||
|
// RSA-1024 self-signed cert (fast for tests)
|
||||||
|
const keys = forge.pki.rsa.generateKeyPair(1024);
|
||||||
|
const cert = forge.pki.createCertificate();
|
||||||
|
cert.publicKey = keys.publicKey;
|
||||||
|
cert.serialNumber = '01';
|
||||||
|
cert.validity.notBefore = new Date();
|
||||||
|
cert.validity.notAfter = new Date();
|
||||||
|
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);
|
||||||
|
|
||||||
|
const attrs = [{ name: 'commonName', value: CN }];
|
||||||
|
cert.setSubject(attrs);
|
||||||
|
cert.setIssuer(attrs);
|
||||||
|
cert.sign(keys.privateKey, forge.md.sha256.create());
|
||||||
|
|
||||||
|
// PEM fixture
|
||||||
|
certPem = forge.pki.certificateToPem(cert);
|
||||||
|
|
||||||
|
// DER fixture — binary encoding required (Pitfall 1)
|
||||||
|
const derBytes = forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes();
|
||||||
|
certDerBuffer = Buffer.from(derBytes, 'binary');
|
||||||
|
}, 15000);
|
||||||
|
|
||||||
|
it('PEM→DER: returns FileResponse with correct mimeType and round-trip identity', async () => {
|
||||||
|
// RED: convertCert throws NotImplementedException — this test will FAIL
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const result = await (service.convertCert({ pemText: certPem, targetFormat: 'der' } as any) as Promise<any>);
|
||||||
|
expect(result.mimeType).toBe('application/x-x509-ca-cert');
|
||||||
|
expect(result.filename).toContain('converted');
|
||||||
|
expect(result.content).toBeTruthy();
|
||||||
|
|
||||||
|
// Round-trip identity: decode base64 DER → re-parse → verify CN matches original
|
||||||
|
const derBuf = Buffer.from(result.content as string, 'base64');
|
||||||
|
const asn1 = forge.asn1.fromDer(forge.util.createBuffer(derBuf.toString('binary')));
|
||||||
|
const reparsed = forge.pki.certificateFromAsn1(asn1);
|
||||||
|
expect(reparsed.subject.getField('CN')?.value).toBe(CN);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('DER→PEM: returned PEM parses to cert with same CN (round-trip identity)', async () => {
|
||||||
|
// RED: convertCert throws NotImplementedException — this test will FAIL
|
||||||
|
const result = await (service.convertCert({
|
||||||
|
file: { originalname: 'c.der', buffer: certDerBuffer },
|
||||||
|
targetFormat: 'pem',
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
} as any) as Promise<any>);
|
||||||
|
expect(result.mimeType).toBe('application/x-pem-file');
|
||||||
|
|
||||||
|
// Decode base64 PEM content → parse → verify CN matches original
|
||||||
|
const pemStr = Buffer.from(result.content as string, 'base64').toString('utf-8');
|
||||||
|
const reparsed = forge.pki.certificateFromPem(pemStr);
|
||||||
|
expect(reparsed.subject.getField('CN')?.value).toBe(CN);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('PEM→P7B: returned P7B contains the original certificate', async () => {
|
||||||
|
// RED: convertCert throws NotImplementedException — this test will FAIL
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const result = await (service.convertCert({ pemText: certPem, targetFormat: 'p7b' } as any) as Promise<any>);
|
||||||
|
expect(result.mimeType).toBe('application/x-pkcs7-certificates');
|
||||||
|
expect(result.filename).toContain('converted');
|
||||||
|
|
||||||
|
// Decode base64 P7B (PEM-wrapped PKCS7) and verify at least 1 cert enclosed
|
||||||
|
const p7bContent = Buffer.from(result.content as string, 'base64').toString('utf-8');
|
||||||
|
const p7 = forge.pkcs7.messageFromPem(p7bContent);
|
||||||
|
expect((p7.certificates as forge.pki.Certificate[]).length).toBeGreaterThanOrEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws BadRequestException for malformed PEM input', async () => {
|
||||||
|
// RED: convertCert throws NotImplementedException (not BadRequestException) — FAIL
|
||||||
|
await expect(
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
service.convertCert({ pemText: 'garbage input not a cert', targetFormat: 'der' } as any),
|
||||||
|
).rejects.toThrow(BadRequestException);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user