You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript/Angular 2解析X509证书并提取公钥

Got it, let's walk through how to extract the public key from an X509 certificate using JavaScript (this works perfectly for Angular 2+ too, since Angular is just built on top of vanilla JS). Here's a complete, tested solution:

Step 1: Understand the Core Tools

We'll use the Web Crypto API (built into modern browsers) to parse the certificate and extract the public key. First, we need to convert the PEM-formatted certificate string into an ArrayBuffer—the format the Web Crypto API expects.

Step 2: Vanilla JavaScript Implementation

Here's a self-contained function set to handle the extraction:

// Helper to convert PEM certificate to ArrayBuffer
function pemToArrayBuffer(pem) {
  // Strip PEM headers/footers and newlines
  const pemHeader = "-----BEGIN CERTIFICATE-----";
  const pemFooter = "-----END CERTIFICATE-----";
  const cleanPem = pem.replace(pemHeader, "").replace(pemFooter, "").replace(/\n/g, "");
  
  // Convert Base64 string to Uint8Array
  const binaryString = window.atob(cleanPem);
  const bytes = new Uint8Array(binaryString.length);
  for (let i = 0; i < binaryString.length; i++) {
    bytes[i] = binaryString.charCodeAt(i);
  }
  return bytes.buffer;
}

// Main function to extract public key
async function extractPublicKeyFromCertificate(pemCertificate) {
  try {
    const certBuffer = pemToArrayBuffer(pemCertificate);
    
    // Import the X509 certificate into the Web Crypto API
    const certificate = await window.crypto.subtle.importCertificate(
      "x509",
      certBuffer,
      {
        name: "RSASSA-PKCS1-v1_5", // Match your cert's algorithm (e.g., "ECDSA" for elliptic curve)
        hash: "SHA-256"
      },
      false, // We don't need to use the cert for signing/encrypting, just extract the key
      ["verify"] // Required key usage for public key extraction
    );
    
    // Extract the public key object from the certificate
    const publicKey = certificate.publicKey;
    
    // Export the public key to SPKI format (PEM-friendly)
    const spkiBuffer = await window.crypto.subtle.exportKey("spki", publicKey);
    
    // Convert ArrayBuffer back to formatted PEM string
    const base64PublicKey = window.btoa(String.fromCharCode(...new Uint8Array(spkiBuffer)));
    return `-----BEGIN PUBLIC KEY-----\n${base64PublicKey.match(/.{1,64}/g).join('\n')}\n-----END PUBLIC KEY-----`;
  } catch (error) {
    console.error("Error extracting public key:", error);
    throw error; // Re-throw to let calling code handle errors
  }
}

// Usage example with your certificate
const certificate = "-----BEGIN CERTIFICATE-----\nMIIFkTCCBHmgAwIBAgIEAOATLTANBgkqhkiG9w0BAQsFADCBkDELMAkGA1UEBhMC\nSU4xKjAoBgNVBAoTIWVNdWRocmEgQ29uc3VtZXIgU2VydmljZXMgTGltaXRlZDEd\nMBsGA1UECxMUQ2VydGlmeWluZyBBdXRob3JpdHkxNjA0BgNVBAMTLWUtTXVkaHJh\nIFN1YiBDQSBmb3...";

extractPublicKeyFromCertificate(certificate)
  .then(publicKeyPem => {
    console.log("Extracted Public Key:", publicKeyPem);
    // Use the public key in your app (e.g., verify signatures, encrypt data)
  })
  .catch(err => {
    // Handle errors like invalid cert format or unsupported algorithms
  });

Step 3: Angular 2+ Adaptation

In Angular, you can wrap this logic into a service for reusability across components:

1. Create a Certificate Service

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class CertificateService {
  constructor() { }

  private pemToArrayBuffer(pem: string): ArrayBuffer {
    const pemHeader = "-----BEGIN CERTIFICATE-----";
    const pemFooter = "-----END CERTIFICATE-----";
    const cleanPem = pem.replace(pemHeader, "").replace(pemFooter, "").replace(/\n/g, "");
    const binaryString = window.atob(cleanPem);
    const bytes = new Uint8Array(binaryString.length);
    for (let i = 0; i < binaryString.length; i++) {
      bytes[i] = binaryString.charCodeAt(i);
    }
    return bytes.buffer;
  }

  async extractPublicKey(pemCertificate: string): Promise<string> {
    try {
      const certBuffer = this.pemToArrayBuffer(pemCertificate);
      const certificate = await window.crypto.subtle.importCertificate(
        "x509",
        certBuffer,
        { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
        false,
        ["verify"]
      );
      const publicKey = certificate.publicKey;
      const spkiBuffer = await window.crypto.subtle.exportKey("spki", publicKey);
      const base64PublicKey = window.btoa(String.fromCharCode(...new Uint8Array(spkiBuffer)));
      return `-----BEGIN PUBLIC KEY-----\n${base64PublicKey.match(/.{1,64}/g).join('\n')}\n-----END PUBLIC KEY-----`;
    } catch (error) {
      console.error("Error extracting public key:", error);
      throw error;
    }
  }
}

2. Use the Service in a Component

import { Component, OnInit } from '@angular/core';
import { CertificateService } from './certificate.service';

@Component({
  selector: 'app-cert-handler',
  templateUrl: './cert-handler.component.html'
})
export class CertHandlerComponent implements OnInit {
  certificate = "-----BEGIN CERTIFICATE-----\nMIIFkTCCBHmgAwIBAgIEAOATLTANBgkqhkiG9w0BAQsFADCBkDELMAkGA1UEBhMC\nSU4xKjAoBgNVBAoTIWVNdWRocmEgQ29uc3VtZXIgU2VydmljZXMgTGltaXRlZDEd\nMBsGA1UECxMUQ2VydGlmeWluZyBBdXRob3JpdHkxNjA0BgNVBAMTLWUtTXVkaHJh\nIFN1YiBDQSBmb3...";
  publicKey: string | null = null;

  constructor(private certService: CertificateService) { }

  ngOnInit(): void {
    this.getPublicKey();
  }

  async getPublicKey(): Promise<void> {
    try {
      this.publicKey = await this.certService.extractPublicKey(this.certificate);
      console.log("Public Key:", this.publicKey);
    } catch (err) {
      console.error("Failed to extract public key:", err);
    }
  }
}

Key Notes

  • Secure Contexts: The Web Crypto API only works over HTTPS or localhost—your production Angular app must use HTTPS.
  • Algorithm Matching: If your certificate uses an elliptic curve algorithm (ECDSA), update the name parameter in importCertificate to "ECDSA" and ensure the hash matches the cert's configured hash (e.g., "SHA-256").
  • PEM Formatting: The match(/.{1,64}/g) line splits the Base64 string into 64-character lines, which is required for valid PEM public key formatting.

内容的提问来源于stack exchange,提问作者pratik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:02:58