cmsdetector

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 23, 2025 License: MIT Imports: 3 Imported by: 0

README

CMS Detector

A Go library for detecting and identifying various CMS (Cryptographic Message Syntax) and PKCS (Public Key Cryptography Standards) formats.

Installation

go get github.com/lEx0/cmsdetector

Features

  • Detection of various PKCS#7 (CMS) structures:
    • PKCS#7 Data
    • PKCS#7 Signed Data
    • PKCS#7 Enveloped Data
    • PKCS#7 Signed And Enveloped Data
    • PKCS#7 Digested Data
    • PKCS#7 Encrypted Data
  • Basic verification of PKCS#12 containers
  • User key detection for PKCS#12 containers (including encrypted keys and NCA user keys)
  • Extraction of CMS structure metadata
  • Compatibility with KalkanCrypt (Kazakhstan's national cryptographic provider) formats and standards

Usage Example

package main

import (
	"fmt"
	"os"

	"github.com/lEx0/cmsdetector"
)

func main() {
	data, err := os.ReadFile("test.cms")
	if err != nil {
		fmt.Printf("Error reading file: %s\n", err)
		return
	}
	
	// Main method for type detection
	result, err := cmsdetector.Detect(data)
	if err != nil {
		fmt.Printf("Analysis error: %s\n", err)
		return
	}
	
	fmt.Printf("File type: %s\n", result.Type)
	fmt.Printf("Encrypted: %v\n", result.IsEncrypted)
	
	if result.ContentType != nil {
		fmt.Printf("OID: %s\n", result.ContentType.String())
	}
	
	// Check for specific type
	if cmsdetector.IsPKCS7SignedData(data) {
		fmt.Println("File contains PKCS#7 signed data")
	}
}

Specialized Checks

// Check for PKCS#7 SignedData
if cmsdetector.IsPKCS7SignedData(data) {
    fmt.Println("Found signed data")
}

// Check for PKCS#7 EnvelopedData
if cmsdetector.IsPKCS7EnvelopedData(data) {
    fmt.Println("Found encrypted data")
}

// Check for PKCS#12
if cmsdetector.IsPKCS12(data) {
    fmt.Println("Found PKCS#12 container")
}

// Check for user PKCS#12 key container (even encrypted)
if cmsdetector.IsUserKeyPKCS12(data) {
    fmt.Println("Found user PKCS#12 key container")
}

Detecting Encrypted PKCS#12 Keys

The library includes specialized detection for encrypted PKCS#12 containers like those used for personal keys:

// Read an encrypted .p12 file
data, err := os.ReadFile("GOST512_112233.p12")
if err != nil {
    fmt.Printf("Error reading file: %s\n", err)
    return
}

// Detect will now handle encrypted containers
result, err := cmsdetector.Detect(data)
if err == nil {
    fmt.Printf("Detected: %s\n", result.Type)
    
    if result.IsEncrypted {
        fmt.Println("This is an encrypted container")
    }
}

Limitations

  • The library only performs type detection of CMS/PKCS data, not full parsing or validation
  • For PKCS#12 containers, basic structure verification is performed, but not content decryption
  • The specialized key detection functions use heuristics and may not be 100% accurate for all cases

KalkanCrypt Compatibility

This library is designed to work with files created by KalkanCrypt, the national cryptographic provider in Kazakhstan. It can detect and identify various cryptographic formats generated by KalkanCrypt, including:

  • CMS/PKCS#7 signed data (digital signatures)
  • PKCS#12 (.p12) key containers
  • Encrypted user key containers (with from National Certification Authority of the Republic of Kazakhstan aka NCA)

This makes the library particularly useful for applications that need to interoperate with the KalkanCrypt ecosystem and NCA (National Certification Authority) of Kazakhstan.

License

MIT

Documentation

Overview

Package cmsdetector provides functions for detecting and identifying various CMS (Cryptographic Message Syntax) and PKCS (Public Key Cryptography Standards) formats.

Example (Detect)

ExampleDetect demonstrates the basic usage of the Detect function

package main

import (
	"fmt"

	"github.com/lEx0/cmsdetector"
)

func main() {
	// In a real application, this would be data from a file
	// Here we'll just use a placeholder to demonstrate the API
	data := []byte("This would be binary CMS data")

	// Try to detect the CMS/PKCS format
	result, err := cmsdetector.Detect(data)
	if err != nil {
		fmt.Printf("Error detecting format: %v\n", err)
		return
	}

	// Use the detection results
	fmt.Printf("Detected format: %s\n", result.Type)
	fmt.Printf("Content type OID: %s\n", result.ContentType.String())

}
Output:

Error detecting format: failed to parse ASN.1 structure: asn1: structure error: tags don't match (16 vs {class:1 tag:20 length:104 isCompound:false}) {optional:false explicit:false application:false private:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} ContentInfo @2
Example (FileDetection)

ExampleFileDetection demonstrates how to detect the format of a file

package main

import (
	"fmt"
	"os"

	"github.com/lEx0/cmsdetector"
)

func main() {
	// Skip this example when running tests
	if os.Getenv("SKIP_FILE_EXAMPLES") != "" {
		fmt.Println("Skipping file example")
		return
	}

	// The path to your CMS/PKCS file
	filePath := "тест.jpg.cms"
	// filePath := "тест.pdf"

	// Read the file
	data, err := os.ReadFile(filePath)
	if err != nil {
		fmt.Printf("Error reading file: %v\n", err)
		return
	}

	// Detect the format
	result, err := cmsdetector.Detect(data)
	if err != nil {
		fmt.Printf("Error detecting format: %v\n", err)
		return
	}

	// Process based on the detected format
	switch {
	case cmsdetector.IsPKCS7SignedData(data):
		fmt.Println("This is a signed PKCS#7 file")
	case cmsdetector.IsPKCS7EnvelopedData(data):
		fmt.Println("This is an enveloped PKCS#7 file")
	case cmsdetector.IsPKCS12(data):
		fmt.Println("This is a PKCS#12 certificate store")
	default:
		fmt.Printf("This is a %s file\n", result.Type)
	}

}
Output:

Error reading file: open тест.jpg.cms: no such file or directory
Example (UsingHelperFunctions)

ExampleUsingHelperFunctions demonstrates how to use the helper functions

package main

import (
	"fmt"

	"github.com/lEx0/cmsdetector"
)

func main() {
	// In a real application, this would be data from a file
	// Here we'll just use a placeholder to demonstrate the API
	data := []byte("This would be binary CMS data")

	// Use the specific format detection functions
	if cmsdetector.IsPKCS7SignedData(data) {
		fmt.Println("This contains PKCS#7 signed data")
	} else {
		fmt.Println("This is not PKCS#7 signed data")
	}

	if cmsdetector.IsPKCS7EnvelopedData(data) {
		fmt.Println("This contains PKCS#7 enveloped data")
	} else {
		fmt.Println("This is not PKCS#7 enveloped data")
	}

	if cmsdetector.IsPKCS12(data) {
		fmt.Println("This is a PKCS#12 container")
	} else {
		fmt.Println("This is not a PKCS#12 container")
	}

}
Output:

This is not PKCS#7 signed data
This is not PKCS#7 enveloped data
This is not a PKCS#12 container

Index

Examples

Constants

View Source
const (
	TypeEncryptedPKCS12 = "Encrypted PKCS#12"
)

Additional type constants for formats that can't be detected via OID

Variables

View Source
var (
	// PKCS#7 OIDs
	PKCS7DataOID               = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1}
	PKCS7SignedDataOID         = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2}
	PKCS7EnvelopedDataOID      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 3}
	PKCS7SignedAndEnvelopedOID = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 4}
	PKCS7DigestedDataOID       = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 5}
	PKCS7EncryptedDataOID      = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 6}

	// Other common OIDs for CMS/PKCS
	PKCS12OID = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 12, 10, 1}
)

OIDs for various types of CMS/PKCS messages

Functions

func GetOIDDescription

func GetOIDDescription(oid asn1.ObjectIdentifier) string

GetOIDDescription returns a human-readable description of the OID

func IsPKCS12

func IsPKCS12(data []byte) bool

IsPKCS12 checks if the data is a PKCS#12 container (including encrypted ones)

func IsPKCS7Data

func IsPKCS7Data(data []byte) bool

IsPKCS7Data checks if the data is PKCS#7 data

func IsPKCS7EnvelopedData

func IsPKCS7EnvelopedData(data []byte) bool

IsPKCS7EnvelopedData checks if the data is PKCS#7 enveloped data

func IsPKCS7SignedData

func IsPKCS7SignedData(data []byte) bool

IsPKCS7SignedData checks if the data is PKCS#7 signed data

func IsUserKeyPKCS12

func IsUserKeyPKCS12(data []byte) bool

IsUserKeyPKCS12 checks if the data appears to be a user PKCS#12 key container

Types

type ContentInfo

type ContentInfo struct {
	ContentType asn1.ObjectIdentifier
	Content     asn1.RawValue `asn1:"explicit,optional,tag:0"`
}

ContentInfo provides the ASN.1 structure for the main CMS/PKCS container

type DetectionResult

type DetectionResult struct {
	Type        string
	ContentType asn1.ObjectIdentifier
	IsEncrypted bool // Indicates if the content is encrypted
}

DetectionResult contains the result of CMS/PKCS type detection

func Detect

func Detect(data []byte) (DetectionResult, error)

Detect tries to determine the type of CMS/PKCS data

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL