forked from CorentinTh/it-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(new tool): SSL Certificate Converter
Fix CorentinTh#1245 Handle JKS, PEM, DER, P12 as input Handle PEM and DER as output
- Loading branch information
Showing
6 changed files
with
316 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { ShieldChevron } from '@vicons/tabler'; | ||
import { defineTool } from '../tool'; | ||
|
||
export const tool = defineTool({ | ||
name: 'SSL Certificate converter', | ||
path: '/ssl-cert-converter', | ||
description: 'Convert SSL Certificate from different formats', | ||
keywords: ['ssl', 'certificate', 'pem', 'der', 'jks', 'converter'], | ||
component: () => import('./ssl-cert-converter.vue'), | ||
icon: ShieldChevron, | ||
createdAt: new Date('2024-08-15'), | ||
}); |
15 changes: 15 additions & 0 deletions
15
src/tools/ssl-cert-converter/ssl-cert-converter.e2e.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { test, expect } from '@playwright/test'; | ||
|
||
test.describe('Tool - Ssl cert converter', () => { | ||
test.beforeEach(async ({ page }) => { | ||
await page.goto('/ssl-cert-converter'); | ||
}); | ||
|
||
test('Has correct title', async ({ page }) => { | ||
await expect(page).toHaveTitle('Ssl cert converter - IT Tools'); | ||
}); | ||
|
||
test('', async ({ page }) => { | ||
|
||
}); | ||
}); |
48 changes: 48 additions & 0 deletions
48
src/tools/ssl-cert-converter/ssl-cert-converter.service.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { Buffer } from 'node:buffer'; | ||
import { describe, expect, it } from 'vitest'; | ||
import { convertCertificate } from './ssl-cert-converter.service'; | ||
|
||
const formatsData = [ | ||
{ | ||
title: 'JKS', | ||
input: Buffer.from( | ||
'/u3+7QAAAAIAAAABAAAAAQAGamtzLWpzAAABeDENGOMAAAB/MH0wDgYKKwYBBAEqAhEBAQUABGstagMT9RkL6lTrGvx2untoFmXM13xjQjMKfxFU/iQHuk3Y44LeB5oP9/e8KEe6nK1NTQhaTRrKyMZGJhs5Oro+TLowYerbBiJJ2DKyBTVjMDCZj8f29hOXpxQpIVv6IEAlFJwL3TQNydxjdgAAAAEABVguNTA5AAAB5jCCAeIwggGHoAMCAQICBCljjXAwDAYIKoZIzj0EAwIFADBmMQ8wDQYDVQQGEwZqa3MtanMxDzANBgNVBAgTBmprcy1qczEPMA0GA1UEBxMGamtzLWpzMQ8wDQYDVQQKEwZsZW5jaHYxDzANBgNVBAsTBmprcy1qczEPMA0GA1UEAxMGamtzLWpzMB4XDTIxMDMxNDE0MDQwNVoXDTIxMDYxMjE0MDQwNVowZjEPMA0GA1UEBhMGamtzLWpzMQ8wDQYDVQQIEwZqa3MtanMxDzANBgNVBAcTBmprcy1qczEPMA0GA1UEChMGbGVuY2h2MQ8wDQYDVQQLEwZqa3MtanMxDzANBgNVBAMTBmprcy1qczBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEXhUAIulQWBEFCRBqPl7t/FKuI6hzWYpdBpwWZSRiDkp9A0xeIJyHazINyyx2xIDyCvR1vrqIhMuFxJIWxp8DmjITAfMB0GA1UdDgQWBBRpec0VpSfJmWjyzDtiUWk5difuTjAMBggqhkjOPQQDAgUAA0cAMEQCIE2hdtgyJZgO+gGZrCBxSgQ7G/uRugeIDGBR5X9oY2rAAiBgRfCUsTPr5NPeTfuS854/koMCTYrvLEcwcRGD4uBuNe3vG6EIUGVgYuXdiR4aycUoOcEb', | ||
'base64'), | ||
pass: 'password', | ||
convertedCount: 1, | ||
}, | ||
{ | ||
title: 'PEM', | ||
input: Buffer.from( | ||
'QmFnIEF0dHJpYnV0ZXMKICAgIGxvY2FsS2V5SUQ6IENGIDVDIDAxIEU4IEQyIDYzIERGIEM4IEZFIDMyIERCIEI0IDI4IDJEIDc2IEYzIEQwIDVEIDUyIEQ4IApzdWJqZWN0PS9DPVVTL1NUPUNhbGlmb3JuaWEvTD1TYW4gRnJhbmNpc2NvL089QmFkU1NML0NOPUJhZFNTTCBDbGllbnQgQ2VydGlmaWNhdGUKaXNzdWVyPS9DPVVTL1NUPUNhbGlmb3JuaWEvTD1TYW4gRnJhbmNpc2NvL089QmFkU1NML0NOPUJhZFNTTCBDbGllbnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkKLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVuVENDQW9XZ0F3SUJBZ0lKQU0xSHg0SkoxT2dwTUEwR0NTcUdTSWIzRFFFQkN3VUFNSDR4Q3pBSkJnTlYKQkFZVEFsVlRNUk13RVFZRFZRUUlEQXBEWVd4cFptOXlibWxoTVJZd0ZBWURWUVFIREExVFlXNGdSbkpoYm1OcApjMk52TVE4d0RRWURWUVFLREFaQ1lXUlRVMHd4TVRBdkJnTlZCQU1NS0VKaFpGTlRUQ0JEYkdsbGJuUWdVbTl2CmRDQkRaWEowYVdacFkyRjBaU0JCZFhSb2IzSnBkSGt3SGhjTk1qUXdPREl3TVRZeU5EUXpXaGNOTWpZd09ESXcKTVRZeU5EUXpXakJ2TVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNBd0tRMkZzYVdadmNtNXBZVEVXTUJRRwpBMVVFQnd3TlUyRnVJRVp5WVc1amFYTmpiekVQTUEwR0ExVUVDZ3dHUW1Ga1UxTk1NU0l3SUFZRFZRUUREQmxDCllXUlRVMHdnUTJ4cFpXNTBJRU5sY25ScFptbGpZWFJsTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEEKTUlJQkNnS0NBUUVBeHpkZkVlc2VUcy9ydWtqbHk2TVNMSE0rUmgwZW5BM0FpNE1qMnNkbDMxeDNTYlBvZW4wOAp1dFZoalBtbHhJVWRraU1HNCtmZmU3TitKdERMRzc1Q2F4WnA5Q3h5dFg3a3l3b29SQkpzUm5RaG1RUGNhOE1SCldBSkJJeit3L0wrM0FGa1RJcVdCZnlUKzFWTzhUVktQa0VwR2RMRG92Wk9telpBQVNpOS9zaitqNmdNN0FhQ2kKRGVaVGYyRVM2NmFiQTVwT3A2MFE2T0Vkd2cvdkNVSmZhcmhLRHBpOXRqM1A2cVRveTlZNERpQlVoT2N0NE1HOAp3NVh3bUtBQytWZm04dGI3dE1pVW9VMHl2S0tPY0w2WVhCWHhCMmtQY09ZeFlOb2JYYXZmVkJFZHdTcmpRN2kvCnMzbzZoa0dRbG05RjdKUEV1VmdibC9KZHdhNjRPWUlxalFJREFRQUJveTB3S3pBSkJnTlZIUk1FQWpBQU1CRUcKQ1dDR1NBR0crRUlCQVFRRUF3SUhnREFMQmdOVkhROEVCQU1DQmVBd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dJQgpBSDlhU2NjMGNQQ2VtUEt3Yk9IY1B1VThON2pINjJoMkxqOGJyZWhlMjZZcXN3dFZYWUN1ZmtLRzFJQkFhNk1XCkxTOHhWVEV0b1ZjOHAwUVZDL3AzTDY1YjB4RG5pUlNCMFArWC9FVWFDNXIzUEE1SmQzVHgzakdBRzgxYjNETVUKMk83L3Jma2ZyZ1hCRUNWQlpRcm1ObVcvWnJpYXI5dmEwKzQwZGFPMTZLUVRRK2tHTDIzdldTWFNKQllJc1FsYgpyU2Y1QWp6eFpXY1Y1aXpUWUZLVjZwWmFsYjNibk8wRmptN2FMWVJZdndqWFhMR2pSb0JYd2xJaVpXRzNWVGJ1CnA5UWlBNEtyS2FvQ2x1bTRCakxtQkVlL1dnK1NVeXdTd2sydkFxUXViVUVtN1l3MmFiL1F3eSttUmIrRTVpaHcKcEhkOUxCaWlGLzBlbVNVbGVJY1NzUWpIend0WWNnQ0M5ZktpYUE1eEhkUXdLY3hOQVRDalZIUUtuMTJpQi92cgpwcVAxRjVHUGhUWk0zWWJ6ZG1wcDdlV0cva2NQRkREQk5CS2xzaXJsR3VRUkVPZ0QweW9pdTg5TG83Q01LV29kClBYbTZrMWxNWS9uRXR0R3VFZm5HR1ZvUUF2SFMvWU5pL3QwVFQ0SlJTMlZBbmZJMGV5K01nVmRCdDVETDMxd3QKa1hIWHh4M2QwV3JmZ0UxSlNvd0NNQ3E4ek1yZGo1UC9vQ0dqYmtsdFJtNnJ2UHZsTmtmRkt0eU42KzV2R0pKMgpWR1BxNnpnTkhmRXVOc1BDRWJ5MExwWm1NSEh6RlhuWjB1d3h6ZnBvVnZqcktYbEFQc1UreGd0K3ZNRzRaZ2VqCjlLTjBmdktnWkZlWWNkZVdsdzR3YThUc0ZadVZVeG1oa3ZsYVJQUlkzenNjCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KQmFnIEF0dHJpYnV0ZXMKICAgIGxvY2FsS2V5SUQ6IENGIDVDIDAxIEU4IEQyIDYzIERGIEM4IEZFIDMyIERCIEI0IDI4IDJEIDc2IEYzIEQwIDVEIDUyIEQ4IApLZXkgQXR0cmlidXRlczogPE5vIEF0dHJpYnV0ZXM+Ci0tLS0tQkVHSU4gRU5DUllQVEVEIFBSSVZBVEUgS0VZLS0tLS0KTUlJRkRqQkFCZ2txaGtpRzl3MEJCUTB3TXpBYkJna3Foa2lHOXcwQkJRd3dEZ1FJcjh6aStFNGwyTElDQWdnQQpNQlFHQ0NxR1NJYjNEUU1IQkFoSEpQUStQVHd3eHdTQ0JNaXVObWlCSGErQmIyWVdGUW1WUzZRYmJBMnlEZFROCmtSamp5K3locG5QSW1UU0plb28xY000UWJRL3owR2c5cUdxZDhNeThKMmtIcFQvNVRWK2VsOHBrbkRtYXYxdG0KMTMwMGlzOXdYd3ZxOUFlTWhSbXJlaFMyeldLYmJDSmk2YkNZczQ2NkZSRy8vRWM5eWZhcUN4blpVVzNhTGlXeApnV2xMeHQyRFRhN1hiTEU2Q1hWaEo4UUNnWGJQcVRRWTYxM1V3KzlRY2xod2t6dXZXYWNwQk5jU2N4dEZhTWZtCkp3UmxWZEdJdUxReDRXckFtUUxjU3J0RlhjMGJwZ1ljRjhqaEsxSTVUaElGNFFCWERlS2FGZFVDbG80NW9XNWIKb0djNXpwd1oraVA3eW96d2c5TnpySTYyam5FMXZBdEtnOWlsQzN0czR4MU9MMktsRXFycUJzbTRLU3c0ZTB6dgpTWUJJRUJuTEFsL0NlK0NLUGZ2TnpKTXpWVHV2Y0MrRGNOUXlmZ2N5bWlVZ2N1SHlkdFFGRi81cU55bjhIT2d2CnoxYm1qR0FBaHJaTHNyajdVWVA3a1FGMzliUlNiZy9Wa1dOa0Z5V2p2REJMc05iMTBXVy8xZEg1ZmJ3YzU4TmcKOTZrT2d3RFJWYWZuVEhtaDI5TzB6QXVMMUFsK0xPUEpnb3JGN0hHYzJneG5vVXEvYk1RREx6MFlSUHJ3eEVnbgpHNnRObTI3THgrZkdvaUdpMnFFUXRWVGErMGl2em1XS3pQbTUxOUU0VU5SR2ZhZGQrdjMrcXBKY3UyR1ZOb0E0Cmdvc2RNbUpYL3kvTkVXSk5kWndHTWpOaGluQW5obDdkL3ZJeVR4aHlvQVhLNExVRkdhWU01L1FYMkFzVjB2ZFUKMTJZWDhnd2ZKMVBYYXhqRGx2ZXp6dTErZTVHbTF5MjI1a0NKU1BNaWpaNE1uMzJnV2lFY0QvN3Vod2dQWkROTQo2clozaWl3K01aaDhqQkQveTBxdTNIdHV4ck0vclRTeERkZVFIb0QydWdnK0lZK0VhMmxsWjI0Sms2Ri9tOG5vCkY2Z3JDODdneEVXdzZIVW8xcE4zVVRzU2l4WCtxaG42eVUzYUJuRWpya0hwQ2ZqOEtNUXV4dXR4cWZDZk1jWmIKaVJpcXIvTmpkYjZ5dUk4OW52OGxVcHRHYjZMZUVEOTc2MGNyNjVhMGh3Ky9rcWZSd0VzUlhRbndYNzEyWHRIRgpVVWlTcmRVd1pGOGdBUFF0dWxmR0tiekllelFVaG9meHFLdUg3NDBtZzFsWmcrNzc2aGtOUGMzOVNNYkJVOEZ5CkYwTllORmhmdnJjbUdIY0Q2b0grZHJvUDJlODhQVXBDU0lHQ0lscm16eHJSOE0rRVR1d1FCOFIyeVFrM1NsN0QKTkh4cXk5RU1KUldVT0JpdmovYjk5QUFkTjE5eWRrZG94VXhOMFlSbWVRMXJGelpvU25OMFBUTjJNSWUvT2lOUApYeEhJZkZIckpSR1NPZm4wU0E0WDdqWHAwZllvUnFMVkJOOGN4bmJLNG5Ma2tob3pVc3BPUGtNVjBONEpLNDBBCkFmc05QTkUyWk1XYmNPbThoZ0ROMk8rVTl5c1NpTnB6akpoOURTWm5OOGR0d1V6NW1WVllaTm1hMExUbXpBME0KMmxKb1JlRGpJUFNaYWE0Q2tWcHhQK29OT1hCN0FMOW1BTnFxc0F4TjhiSjg1UUlSaXRDSEw5YW5oa1lsWGQyNwp1Sld6RWhJbGh6MjM4ZVlmL09KOUNQVkhoMVdmZHZlRndUM0Z4ZXZYaVNlcnVCT1M4UXp3QXJ5eGVxL0l4VmNqCnRSV25OQ2VVQTlqa3BJRktRd05CZ294K2tzU3BNN2t3eXd6dHFNV2F3aHNlSUNCMk9MTDBpaksyVVFaeHp4bTYKQnkvUmt0Qlg0RzI5Wk0wU05uOThNaXdKdW9TMHFvRlg4bVc2MExMWWdtMzZpazR1NTJvWm1CdzNScDVhZGF6cQo4UXREeEs2WDB0bVRUYVVteXB1SmIwUEdRN202c0dVc2h5SnNUTWd3Yi8zREljUFRZaENSRVVOeVVMdlk2MmhSCko5Q3c2aURGRVMzSDNjcjQ1QlRLZHJ3K1R1amFRRWdOUUJpMXNRVTFWUlVmVm5LNURhUjNkU2tEMTBxWmR5Q0EKV0JFPQotLS0tLUVORCBFTkNSWVBURUQgUFJJVkFURSBLRVktLS0tLQo=', | ||
'base64').toString('binary'), | ||
|
||
pass: '', | ||
convertedCount: 1, | ||
}, | ||
{ | ||
title: 'DER', | ||
input: Buffer.from( | ||
'MIIC+zCCAeOgAwIBAgIJAOxwUeP5dw46MA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xNzA1MzExNDExNTNaFw00NDEwMTYxNDExNTNaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALEPP29L/6fGvrA6wVD1kaPMS5o2O8h7AwIgnV8Fne74q/5NyMWrd/s5jAzug+yMRqLD8UbrA2s9vwKwkflKxHFZeIh1BtttTd31HmyPiE5tqp2/N2SqIm6bVb/8R4+i6CkW+K8SWk4+hQbEeAaAzNxq1oH/QKqkq1CzVsTjoLiUW2+dWw1iC0ZGefoablyICuIfBBH4OSK5KOKA8oKdOHoucYMOHXbXvsJVaNP+wJa8+qaDot45s2tliDljX06xNzOwSWSGzFbjiyEm5YuhO1VEIojQ+fe4EfToD00OrC5eTUI2BQ5eJ7FA8udjqAE86xmj9f63GxTbHvUyXx3ve8MCAwEAAaNQME4wHQYDVR0OBBYEFLW83bDG7ZWwluyWcueSk5A/hCk6MB8GA1UdIwQYMBaAFLW83bDG7ZWwluyWcueSk5A/hCk6MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAIfVtAO6VOwUQ2zp4QI698uV3ESxYIg1K6kTTWkvXkvYMlG5Wuvsan83V4zCTpclKSqePPr73eN9HkcGEOEXU+zM1eS4RfW8TDj9eLbGt0cBGzWC4gXJiMEx6Rr0VpcnjF5u9Iqty+YWQ/8MH10kTeOojuAtOmcrVe3VwB8bDx+PwHd0ZZCTWxi+qU/ST5jOEokiihaW68aHOc6IXgNRChPpI01gZVUFRevaJP5g1Yk41cSegGEPkmNO1X8ps2wrIzV28Ih5u7GiW1Gca+MwAAErzf8HsbGwZc56AXnpqKpM55T1cmfwPQe36lyUk8Cz/WzivmwsfbIlGRreK8kwCpc=', | ||
'base64').toString('binary'), | ||
pass: '', | ||
convertedCount: 1, | ||
}, | ||
{ | ||
title: 'P12', | ||
input: Buffer.from( | ||
'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', | ||
'base64').toString('binary'), | ||
pass: 'chef$123', | ||
convertedCount: 1, | ||
}, | ||
]; | ||
|
||
describe('ssl-cert-converter', () => { | ||
for (const format of formatsData) { | ||
const { input, pass, convertedCount, title } = format; | ||
it(`Convert '${title}' format to correct values`, () => { | ||
expect(convertCertificate(input, pass)).toHaveLength(convertedCount); | ||
}); | ||
} | ||
}); |
119 changes: 119 additions & 0 deletions
119
src/tools/ssl-cert-converter/ssl-cert-converter.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import type { Buffer } from 'node:buffer'; | ||
import { | ||
parseCertificate, | ||
} from 'sshpk'; | ||
|
||
import type { | ||
Certificate, | ||
CertificateFormat, | ||
} from 'sshpk'; | ||
|
||
import * as forge from 'node-forge'; | ||
import jks from 'jks-js'; | ||
|
||
function convertPKCS12ToPem(p12base64: forge.Bytes | forge.util.ByteBuffer, password: string) { | ||
const p12Asn1 = forge.asn1.fromDer(p12base64, false); | ||
const p12 = forge.pkcs12.pkcs12FromAsn1(p12Asn1, false, password); | ||
|
||
const pemKey = getKeyFromP12(p12); | ||
const { pemCertificate, commonName } = getCertificateFromP12(p12); | ||
|
||
return { pemKey, pemCertificate, commonName }; | ||
} | ||
|
||
function getKeyFromP12(p12: forge.pkcs12.Pkcs12Pfx) { | ||
const keyData = p12.getBags({ bagType: forge.pki.oids.pkcs8ShroudedKeyBag }); | ||
let pkcs8Key = keyData[forge.pki.oids.pkcs8ShroudedKeyBag]![0]; | ||
|
||
if (typeof pkcs8Key === 'undefined') { | ||
pkcs8Key = keyData[forge.pki.oids.keyBag]![0]; | ||
} | ||
|
||
if (typeof pkcs8Key === 'undefined') { | ||
throw new TypeError('Unable to get private key.'); | ||
} | ||
|
||
return forge.pki.privateKeyToPem(pkcs8Key.key!); | ||
} | ||
|
||
function getCertificateFromP12(p12: any) { | ||
const certData = p12.getBags({ bagType: forge.pki.oids.certBag }); | ||
const certificate = certData[forge.pki.oids.certBag][0]; | ||
|
||
const pemCertificate = forge.pki.certificateToPem(certificate.cert); | ||
const commonName = certificate.cert.subject.attributes[0].value; | ||
return { pemCertificate, commonName }; | ||
} | ||
|
||
export function convertCertificate( | ||
inputKeyOrCertificateValue: string | Buffer, | ||
password: string) { | ||
const canParse = (value: any, parseFunction: (value: any) => any) => { | ||
try { | ||
return parseFunction(value); | ||
} | ||
catch (e: any) { | ||
// console.log(e); | ||
return null; | ||
} | ||
}; | ||
|
||
const cert = canParse(inputKeyOrCertificateValue, (value) => { | ||
for (const format of ['openssh', 'pem', 'x509']) { | ||
try { | ||
return parseCertificate(value, format as CertificateFormat); | ||
} | ||
catch { | ||
} | ||
} | ||
return null; | ||
}) as Certificate; | ||
if (cert) { | ||
return [{ | ||
alias: '#default', | ||
key: null, | ||
der: canParse(cert, c => c.toBuffer('x509')), | ||
pem: cert.toString('pem'), | ||
}]; | ||
} | ||
|
||
const pkcs12 = canParse(inputKeyOrCertificateValue, (value) => { | ||
return convertPKCS12ToPem(forge.util.createBuffer(value, 'raw'), password); | ||
}); | ||
if (pkcs12) { | ||
return [{ | ||
alias: pkcs12.commonName, | ||
key: pkcs12.pemKey, | ||
der: canParse(pkcs12.pemCertificate, pemCert => parseCertificate(pemCert, 'pem').toBuffer('x509')), | ||
pem: pkcs12.pemCertificate, | ||
}]; | ||
} | ||
|
||
const parsedJKS = canParse(inputKeyOrCertificateValue, (value) => { | ||
return jks.toPem( | ||
value, | ||
password, | ||
); | ||
}); | ||
if (parsedJKS) { | ||
return Object.entries(parsedJKS).map(([k, v]) => { | ||
if (typeof v === 'string') { | ||
return { | ||
alias: k, | ||
key: null, | ||
der: canParse(v, pemCert => parseCertificate(pemCert, 'pem').toBuffer('x509')), | ||
pem: v, | ||
}; | ||
} | ||
const { cert, key } = v as { cert: string; key: string }; | ||
return { | ||
alias: k, | ||
key, | ||
der: canParse(cert, pemCert => parseCertificate(pemCert, 'pem').toBuffer('x509')), | ||
pem: cert, | ||
}; | ||
}); | ||
} | ||
|
||
return null; | ||
} |
Oops, something went wrong.