Create and verify digital signatures for messages and cleartext. Supports detached signatures, multiple signing keys, and comprehensive signature verification with detailed results.
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' }
]
});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
});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);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>;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[]>;
}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[];
}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
}
]
});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' }
]
});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);
}
}