or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

encryption-decryption.mdindex.mdkey-management.mdpacket-api.mdsession-keys.mdsigning-verification.md
tile.json

signing-verification.mddocs/

Signing and Verification

Create and verify digital signatures for messages and cleartext. Supports detached signatures, multiple signing keys, and comprehensive signature verification with detailed results.

Capabilities

Message Signing

Sign messages and cleartext with private keys.

/**
 * Sign a message or cleartext message
 * @param options - Signing options
 * @returns Promise resolving to signed message
 */
function sign(options: SignOptions): Promise<string | Uint8Array>;

interface SignOptions {
  /** Message or cleartext message to sign */
  message: CleartextMessage | Message;
  /** Private keys for signing */
  signingKeys: PrivateKey | PrivateKey[];
  /** Output format */
  format?: 'armored' | 'binary' | 'object';
  /** Create detached signature */
  detached?: boolean;
  /** Key IDs for signing */
  signingKeyIDs?: KeyID | KeyID[];
  /** Override signature date */
  date?: Date;
  /** User IDs for signing */
  signingUserIDs?: UserID | UserID[];
  /** Signature notations */
  signatureNotations?: RawNotation | RawNotation[];
  /** Custom configuration */
  config?: PartialConfig;
}

Usage Examples:

import { createMessage, sign, createCleartextMessage } from 'openpgp';

// Sign a message
const message = await createMessage({ text: 'Hello, World!' });
const signedMessage = await sign({
  message,
  signingKeys: privateKey,
  format: 'armored'
});

// Create detached signature
const detachedSig = await sign({
  message,
  signingKeys: privateKey,
  detached: true,
  format: 'armored'
});

// Sign cleartext message
const cleartextMsg = await createCleartextMessage({ text: 'Hello, World!' });
const signedCleartext = await sign({
  message: cleartextMsg,
  signingKeys: privateKey,
  format: 'armored'
});

// Sign with multiple keys
const multiSigned = await sign({
  message,
  signingKeys: [privateKey1, privateKey2],
  signingUserIDs: [
    { name: 'Alice', email: 'alice@example.com' },
    { name: 'Bob', email: 'bob@example.com' }
  ]
});

Message Verification

Verify signatures on messages and cleartext.

/**
 * Verify signatures on a message or cleartext message
 * @param options - Verification options
 * @returns Promise resolving to verification results
 */
function verify(options: VerifyOptions): Promise<VerifyMessageResult>;

interface VerifyOptions {
  /** Message or cleartext message with signatures */
  message: CleartextMessage | Message;
  /** Public keys for verification */
  verificationKeys: PublicKey | PublicKey[];
  /** Require signed message */
  expectSigned?: boolean;
  /** Output data format */
  format?: 'utf8' | 'binary';
  /** Detached signature for verification */
  signature?: Signature;
  /** Date for verification */
  date?: Date;
  /** Custom configuration */
  config?: PartialConfig;
}

interface VerifyMessageResult {
  /** Original message data */
  data: string | Uint8Array | ReadableStream<string> | ReadableStream<Uint8Array>;
  /** Signature verification results */
  signatures: VerificationResult[];
}

interface VerificationResult {
  /** Key ID that created the signature */
  keyID: KeyID;
  /** Promise that resolves if signature is valid */
  verified: Promise<true>;
  /** Promise that resolves to the signature object */
  signature: Promise<Signature>;
}

Usage Examples:

import { readMessage, verify, readCleartextMessage } from 'openpgp';

// Verify signed message
const message = await readMessage({ armoredMessage: signedData });
const verification = await verify({
  message,
  verificationKeys: publicKey
});

console.log('Original data:', verification.data);

// Check each signature
for (const result of verification.signatures) {
  try {
    await result.verified;
    console.log('Valid signature from key:', result.keyID.toHex());
    
    const sig = await result.signature;
    console.log('Signature created:', sig.created);
  } catch (error) {
    console.log('Invalid signature from key:', result.keyID.toHex(), error.message);
  }
}

// Verify cleartext message
const cleartextMessage = await readCleartextMessage({ 
  cleartextMessage: cleartextData 
});
const cleartextVerification = await verify({
  message: cleartextMessage,
  verificationKeys: [publicKey1, publicKey2]
});

// Verify with detached signature
const messageToVerify = await readMessage({ armoredMessage: originalMessage });
const detachedSignature = await readSignature({ armoredSignature: sigData });
const detachedVerification = await verify({
  message: messageToVerify,
  verificationKeys: publicKey,
  signature: detachedSignature
});

// Require signed message (throws if not signed)
const verifiedSigned = await verify({
  message,
  verificationKeys: publicKey,
  expectSigned: true
});

Cleartext Message Handling

Work with cleartext signed messages.

/**
 * Create a cleartext message
 * @param options - Cleartext message options
 * @returns Promise resolving to CleartextMessage
 */
function createCleartextMessage(options: { text: string }): Promise<CleartextMessage>;

/**
 * Read a cleartext message from armored data
 * @param options - Reading options
 * @returns Promise resolving to CleartextMessage
 */
function readCleartextMessage(options: { 
  cleartextMessage: string, 
  config?: PartialConfig 
}): Promise<CleartextMessage>;

Usage Examples:

import { createCleartextMessage, sign, readCleartextMessage, verify } from 'openpgp';

// Create and sign cleartext message
const cleartextMsg = await createCleartextMessage({ 
  text: 'This is a cleartext message that will be signed.' 
});

const signedCleartext = await sign({
  message: cleartextMsg,
  signingKeys: privateKey
});

// Read and verify cleartext message
const readCleartext = await readCleartextMessage({ 
  cleartextMessage: signedCleartext 
});

const verification = await verify({
  message: readCleartext,
  verificationKeys: publicKey
});

console.log('Cleartext:', verification.data);
console.log('Signatures valid:', verification.signatures.length > 0);

Signature Handling

Work directly with signature objects.

/**
 * Read a signature from armored data
 * @param options - Signature reading options
 * @returns Promise resolving to Signature object
 */
function readSignature(options: { 
  armoredSignature: string, 
  config?: PartialConfig 
}): Promise<Signature>;

/**
 * Read a signature from binary data
 * @param options - Signature reading options
 * @returns Promise resolving to Signature object
 */
function readSignature(options: { 
  binarySignature: Uint8Array, 
  config?: PartialConfig 
}): Promise<Signature>;

Classes

CleartextMessage Class

class CleartextMessage {
  /** Get ASCII armored representation */
  armor(config?: Config): string;
  /** Get signing key IDs */
  getSigningKeyIDs(): KeyID[];
  /** Get cleartext content */
  getText(): string;
  /** Sign the cleartext message */
  sign(
    privateKeys: PrivateKey[], 
    signature?: Signature, 
    signingKeyIDs?: KeyID[], 
    date?: Date, 
    userIDs?: UserID[], 
    notations?: RawNotation[], 
    config?: Config
  ): void;
  /** Verify signatures */
  verify(keys: PublicKey[], date?: Date, config?: Config): Promise<VerificationResult[]>;
}

Signature Class

class Signature {
  /** Packet list containing signature data */
  readonly packets: PacketList<SignaturePacket>;
  
  constructor(packetlist: PacketList<SignaturePacket>);
  
  /** Get binary representation */
  write(): Uint8Array | ReadableStream<Uint8Array>;
  /** Get ASCII armored representation */
  armor(config?: Config): string;
  /** Get signing key IDs */
  getSigningKeyIDs(): KeyID[];
}

Advanced Signature Features

Signature Notations

Add custom notations to signatures.

import { sign } from 'openpgp';

const signedWithNotations = await sign({
  message,
  signingKeys: privateKey,
  signatureNotations: [
    {
      name: 'issuer@example.com',
      value: new TextEncoder().encode('Issued by Example Corp'),
      humanReadable: true,
      critical: false
    },
    {
      name: 'policy@example.com', 
      value: new TextEncoder().encode('https://example.com/signature-policy'),
      humanReadable: true,
      critical: true
    }
  ]
});

Multiple Key Signing

Sign with multiple keys for stronger authentication.

import { sign } from 'openpgp';

const multiKeySigned = await sign({
  message,
  signingKeys: [primaryKey, backupKey],
  signingKeyIDs: [primaryKeyID, backupKeyID],
  signingUserIDs: [
    { name: 'Primary Signer', email: 'primary@example.com' },
    { name: 'Backup Signer', email: 'backup@example.com' }
  ]
});

Signature Verification Details

import { verify } from 'openpgp';

const verification = await verify({
  message,
  verificationKeys: [key1, key2, key3]
});

for (const result of verification.signatures) {
  const signature = await result.signature;
  
  console.log('Key ID:', result.keyID.toHex());
  console.log('Signature type:', signature.packets[0].signatureType);
  console.log('Hash algorithm:', signature.packets[0].hashAlgorithm);
  console.log('Creation time:', signature.packets[0].created);
  console.log('Expiration:', signature.packets[0].getExpirationTime());
  
  // Check if signature is valid
  try {
    await result.verified;
    console.log('✓ Signature is valid');
  } catch (error) {
    console.log('✗ Signature is invalid:', error.message);
  }
}