kalkan

package module
v0.6.2 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: MIT Imports: 23 Imported by: 0

README

KalkanCrypt for Go

Русская версия

CI Go Reference

Go wrapper for KalkanCrypt. The root package exposes typed operations over the lower-level ckalkan binding.

Compatibility

  • Go 1.26+
  • linux/amd64 with CGO_ENABLED=1
  • windows/amd64

Native CI exercises libkalkancryptwr-64.so.2.0.13.

windows/386, Linux with CGO_ENABLED=0, and other targets compile against the unsupported driver and return ErrUnavailable.

Obtain the SDK from the NCA RK developer portal. WithLibraryPath requires an absolute path to the x64 .so or DLL.

Install

go get github.com/skarm/kalkan@latest

Packages

Use ckalkan when the root package does not expose the required operation. Use it to build a custom high-level layer over KalkanCrypt with its own request types, validation, buffer policies, logging, or error mapping.

ckalkan closely mirrors the native API. Calling code owns native flags, encodings, buffer sizing, and status-code handling; it must also account for client lifecycle, ABI constraints, and any required process isolation.

Low-level output buffers

The ckalkan buffer options cover two ABI shapes:

  • WithListBufferSize sets the initial allocation for KC_GetTokens and KC_GetCertificatesList; the default is 1 MiB. In the tested Linux SDK 2.0.13, these functions receive no byte-capacity argument, and tk_count and cert_count are output item counts. The option controls allocation size but does not bound the native write.
  • WithBufferSize sets the global initial capacity for length-aware output calls when a request does not specify its own capacity. Without this option, operation-specific defaults are 128 bytes for hashes, 4 KiB for metadata, 8 KiB for certificates, and 64 KiB for signatures and generic outputs. Attached CMS uses the in-memory input or file size plus a conservative signature reserve; CMS Base64 and PEM expansion is included. Signed XML/WSSE uses the in-memory XML size plus the same reserve (KC_IN_FILE is not supported by these two SDK calls). These calls initialize an output-length parameter with the capacity and retry after KCR_BUFFER_TOO_SMALL.
  • Every output buffer has a 64 MiB hard limit by default (ckalkan.DefaultMaxOutputBufferSize). WithMaxBufferSize(0) restores that safe default; a positive value deliberately selects a smaller or larger limit, up to the native C int maximum of 2^31-1 bytes. A negative value makes New return ErrInvalidOutputBufferSize. If native code reports that more than the active limit is required, the wrapper returns a typed OutputBufferLimitError containing the operation, requested size, and applied limit before retrying with or allocating the oversized capacity.

On Linux, ZipConVerify requires a 64 KiB safety allocation because SDK 2.0.13 can write past a smaller reported capacity. If an explicit hard limit is below that safety minimum, the call fails before entering the native library.

Positive WithBufferSize and WithListBufferSize values are normalized to at least 64 KiB. Positive WithMaxBufferSize values are honored exactly up to the C int ABI maximum. A smaller hard limit may prevent an operation from using its usual initial capacity; the 64 MiB default is a security and availability boundary, not an indication that an operation should normally use that much memory.

The allocation limit also bounds wrapper retries for KC_GetTokens and KC_GetCertificatesList, but it does not fix their separate ABI risk: those two functions receive no byte-capacity argument, so even the initial native write cannot be bounded by this option.

An apparently successful list result that occupies the entire allocation without a NUL terminator is treated as potentially truncated and retried with a larger allocation.

Client usage

import (
	"context"
	"errors"
	"os"

	"github.com/skarm/kalkan"
)

func hash(ctx context.Context) (digest *kalkan.Digest, err error) {
	client, err := kalkan.Open(ctx,
		kalkan.WithLibraryPath(os.Getenv("KALKANCRYPT_LIBRARY")),
	)
	if err != nil {
		return nil, err
	}
	defer func() {
		err = errors.Join(err, client.Close())
	}()

	return client.Hash(ctx, kalkan.HashRequest{
		Algorithm: kalkan.GOST2015_512,
		Data:      kalkan.Bytes([]byte("document payload")),
	})
}

Open configures these production endpoints by default:

  • TSA: http://tsp.pki.gov.kz:80
  • OCSP: http://ocsp.pki.gov.kz

The corresponding test endpoints are:

  • TSA: http://test.pki.gov.kz/tsp/
  • OCSP: http://test.pki.gov.kz/ocsp/

Configure the test pair explicitly when required:

client, err := kalkan.Open(ctx,
	kalkan.WithLibraryPath(os.Getenv("KALKANCRYPT_LIBRARY")),
	kalkan.WithTSAURL("http://test.pki.gov.kz/tsp/"),
	kalkan.WithOCSPURL("http://test.pki.gov.kz/ocsp/"),
)

WithTSAURL and WithOCSPURL can be set independently. Signing operations require LoadKeyStore; see the package examples.

Runtime model

KalkanCrypt state is process-global. Native calls are serialized. context.Context cancels lock acquisition but cannot interrupt a call after control enters KalkanCrypt.

Client.Close() waits for the active call and can block indefinitely. Client.CloseContext(ctx) stops the caller’s wait on ctx.Err(), leaves the client in closing state, and rejects new operations. Enforce hard native-call deadlines with process isolation.

On Windows, LoadLibraryExW uses LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS. The current working directory and PATH are excluded. Narrow char* arguments are encoded as UTF-8 with a terminating NUL.

Inputs and bounds

Operations use Source values:

  • kalkan.Bytes(data): raw in-memory bytes for payloads, XML, or already-decoded binary data; the operation selects the field-specific native flags
  • kalkan.Base64(data): in-memory input that already contains Base64 text; the constructor does not encode data
  • kalkan.PEM(data): an existing PEM representation; the constructor does not create the PEM envelope
  • kalkan.DER(data): an existing DER representation, used to select DER explicitly for CMS and certificate inputs
  • kalkan.File(path): a path forwarded to KalkanCrypt by operations that support KC_IN_FILE

Supported variants are operation-specific.

The in-memory constructors neither copy nor transform the provided byte slice. Operation-specific validation may decode PEM or Base64 before the native call. On Linux and Windows, length-delimited in-memory inputs are passed directly to KalkanCrypt without an adapter copy. File forwards the original path after empty-path and NUL validation; the native adapter adds the C-string terminator required by KC_IN_FILE. Keep borrowed slices and referenced files unchanged until the call returns.

WithMaxInputSize caps high-level in-memory inputs. It does not apply to file sources or native output buffers. Native output buffers have a 64 MiB hard limit by default (kalkan.DefaultMaxOutputBufferSize). WithMaxOutputBufferSize(0) restores that default; a positive value selects a smaller or larger limit (up to the native C int maximum), and a negative value makes Open return ErrInvalidInput. The option is forwarded to ckalkan.WithMaxBufferSize. Exceeding the active limit returns ckalkan.OutputBufferLimitError before an oversized retry or allocation.

Native binary outputs are returned strictly according to the SDK-reported outLen; zero bytes inside that range are preserved. The returned slice has len and cap limited to the logical result, so unused buffer capacity is not exposed. Byte-slice results are bounded views rather than copies: keeping a result alive also retains the successful native backing allocation, avoiding a second large allocation and copy. Known textual outputs use C-string semantics and end at the first NUL because some KalkanCrypt methods report a fixed-size block and leave unspecified bytes after the terminator.

KeyStore.Password and Proxy.Password are strings. Go memory, KalkanCrypt state, and SDK-internal copies cannot be zeroized by this package.

CMS and digest signing

CMS output is raw DER by default. Select CMSOutputBase64 or CMSOutputPEM for text output.

SignHashRequest.Digest is the precomputed digest. DigestAlgorithm must match the digest algorithm; its zero value is SHA256. Use GOST2015_512 for GOST R 34.11-2015 512-bit digests.

XML and WS-Security

VerifyXML delegates cryptographic verification to KalkanCrypt. For SOAP 1.1 and SOAP 1.2, ExpectedBodyID is required and the wrapper enforces:

  • exactly one ds:Signature
  • exactly one direct-child ds:SignedInfo
  • exactly one SOAP Body that is a direct child of the Envelope and has the expected wsu:Id
  • a direct ds:Reference to #ExpectedBodyID
  • the Body reference has either no ds:Transforms, or exactly one direct ds:Transform using Exclusive XML Canonicalization (http://www.w3.org/2001/10/xml-exc-c14n#)
  • no duplicate matching wsu:Id, xml:id, Id, or ID

XML operations accept kalkan.Bytes; file and pre-encoded sources are rejected.

Additional direct references may cover other WS-Security nodes. SOAP input must be UTF-8. Non-SOAP XML accepts UTF-8 or an ASCII-compatible declared encoding when the prolog and root tag are ASCII.

The wrapper does not independently allowlist CanonicalizationMethod, DigestMethod, or SignatureMethod: the supported cryptographic algorithms depend on the installed KalkanCrypt version and repository fixtures do not establish a stable complete set. KalkanCrypt remains responsible for rejecting unsupported methods.

Certificate validation

ValidateCertificateRequest.Mode must be one of CertificateValidationOCSP, CertificateValidationCRL, or CertificateValidationNone. The zero value is invalid. CertificateValidationNone explicitly disables external revocation checks.

Certificate input supports DER, PEM, and base64; kalkan.File is rejected. PEM input must contain exactly one CERTIFICATE block. RevocationSource is a CRL path in CRL mode and an OCSP URL override in OCSP mode.

WithOCSPURL and WithTSAURL override the package defaults. URL validation checks syntax but does not restrict the destination.

Use X509CertificateGetInfoFields on metadata hot paths. CertificateInfo exposes IIN, BIN, subject type, and recognized NCA roles when the corresponding fields are requested.

ZIP containers

SignZIPRequest.OutputPath must end with .zip, case-insensitively. Existing requested and normalized output paths are rejected before the native call. KalkanCrypt creates the file without an atomic create-if-absent guarantee.

ZIP input paths are forwarded after empty-path and NUL validation. Keep the files unchanged until each operation returns.

VerifyZIP and ExtractZIPSignerCertificate are independent. Certificate extraction does not verify the ZIP signature. Call VerifyZIP first when both results are required.

Checks

make check
KALKANCRYPT_LIBRARY=/opt/kalkan/lib/libkalkancryptwr-64.so \
KALKANCRYPT_SDK_ASSETS=./testdata \
LD_LIBRARY_PATH=/opt/kalkan/lib \
make test-native

make docker-test expects the Linux SDK libraries under .local/kalkancrypt/lib/linux/.

On Windows:

$env:KALKANCRYPT_LIBRARY = "C:\KalkanCrypt\KalkanCrypt.dll"
go test ./...

Project policies

The repository license does not grant rights to KalkanCrypt SDK binaries.

Documentation

Overview

Package kalkan provides an application-level Go API for KalkanCrypt.

The package supports hashing, CMS signatures, XML signatures, WS-Security signing, KalkanCrypt ZIP containers, certificate loading, and certificate validation. Inputs are described with typed request structs and Source values, so callers can choose in-memory data or native file paths without passing native KalkanCrypt flags through application code. Source retains caller-provided byte slices; do not mutate them until the operation returns. File source paths are passed unchanged after validation.

VerifyXML requires ExpectedBodyID for SOAP envelopes. Accepted non-SOAP input is passed to KalkanCrypt unchanged.

Native calls are process-global and serialized. Context cancellation stops lock waits but cannot interrupt an active KalkanCrypt call; hard deadlines require process isolation.

Open requires WithLibraryPath with an absolute path to the native KalkanCrypt library. Passwords passed as Go strings cannot be zeroized by this package.

Index

Examples

Constants

CertificateInfoAllFields requests the same properties as X509CertificateGetInfo.

View Source
const (

	// DefaultMaxOutputBufferSize is the default hard limit for each native
	// output buffer. It is a security and availability boundary, not a promise
	// that any operation should consume the full amount. Applications may set a
	// smaller limit with WithMaxOutputBufferSize.
	DefaultMaxOutputBufferSize = ckalkan.DefaultMaxOutputBufferSize
)

Variables

View Source
var (
	// ErrInvalidInput is wrapped by validation errors raised before native calls.
	ErrInvalidInput = errors.New("kalkan: invalid input")

	// ErrClosed is returned when a Client method is called after Close.
	ErrClosed = errors.New("kalkan: client is closed")

	// ErrUnavailable is returned when the native KalkanCrypt loader is
	// unavailable for the current build/platform.
	ErrUnavailable = errors.New("kalkan: native KalkanCrypt loader is unavailable")
)

Functions

This section is empty.

Types

type CMS

type CMS struct {
	// Data contains CMS output bytes. By default this is raw DER CMS; when a
	// signing request sets OutputFormat, Data contains native base64 or PEM
	// text bytes instead.
	Data []byte
}

CMS is a CMS signature returned by SignCMS.

type CMSOutputFormat

type CMSOutputFormat int

CMSOutputFormat selects the representation returned by CMS signing operations.

const (
	// CMSOutputDER returns raw binary ASN.1 DER CMS bytes. This is the default
	// output format and can be passed back to VerifyCMS using Bytes or DER
	// sources.
	CMSOutputDER CMSOutputFormat = iota
	// CMSOutputBase64 returns base64 text for the DER CMS bytes, without PEM
	// header/footer armor. Use it for text-only transports or JSON fields.
	CMSOutputBase64
	// CMSOutputPEM returns PEM-armored text: base64 DER plus header/footer and
	// line wrapping. Use it for copy/paste workflows and PEM-oriented tools.
	CMSOutputPEM
)

type CertificateFormat

type CertificateFormat int

CertificateFormat identifies certificate byte encoding.

const (
	// CertificateDER is DER binary certificate data.
	CertificateDER CertificateFormat = iota
	// CertificatePEM is PEM text certificate data.
	CertificatePEM
	// CertificateBase64 is base64 certificate data.
	CertificateBase64
)

type CertificateInfo

type CertificateInfo struct {
	// Subject is the native subject distinguished name string.
	Subject string
	// SerialNumber is the native certificate serial number string.
	SerialNumber string
	// ValidFrom is the parsed native notBefore value.
	ValidFrom time.Time
	// ValidUntil is the parsed native notAfter value.
	ValidUntil time.Time
	// Issuer is the native issuer distinguished name string.
	Issuer string
	// Policy is the native certificate policies string.
	Policy string
	// KeyUsage is the native key usage string.
	KeyUsage string
	// ExtKeyUsage is the native extended key usage string.
	ExtKeyUsage string
	// AuthKeyID is the native authority key identifier string.
	AuthKeyID string
	// SubjKeyID is the native subject key identifier string.
	SubjKeyID string
	// AlgorithmSignCert is the native certificate signature algorithm string.
	AlgorithmSignCert string
	// PublicKey is the native public key string.
	PublicKey string
	// OCSPURL is the native OCSP responder string.
	OCSPURL string
	// CRLURL is the native CRL distribution point string.
	CRLURL string
	// DeltaCRLURL is the native delta CRL distribution point string.
	DeltaCRLURL string
	// SubjectCountry is the native subject country value.
	SubjectCountry string
	// SubjectSerialNumber is the native subject serialNumber value.
	SubjectSerialNumber string
	// SubjectOrganization is the native subject organization value.
	SubjectOrganization string
	// SubjectOrganizationalUnit is the native subject organizational unit value.
	SubjectOrganizationalUnit string
	// Policies contains parsed values from Policy.
	Policies []string
	// KeyUsages contains parsed values from KeyUsage.
	KeyUsages []string
	// ExtKeyUsages contains parsed values from ExtKeyUsage.
	ExtKeyUsages []string
	// IIN is parsed from Kazakhstan subject serialNumber values prefixed with "IIN".
	IIN string
	// BIN is parsed from Kazakhstan subject OU values prefixed with "BIN".
	BIN string
	// SubjectType is inferred from known Kazakhstan NCA policy OIDs or IIN/BIN.
	SubjectType CertificateSubjectType
	// Roles contains recognized Kazakhstan NCA role policy OIDs.
	Roles []CertificateRole
}

CertificateInfo contains selected KalkanCrypt certificate properties.

type CertificateInfoField

type CertificateInfoField uint64

CertificateInfoField selects certificate properties requested from KalkanCrypt. Use X509CertificateGetInfo for the full legacy set.

const (
	// CertificateInfoSubject requests the native subject distinguished name.
	CertificateInfoSubject CertificateInfoField = 1 << iota
	// CertificateInfoSerialNumber requests the native serial number.
	CertificateInfoSerialNumber
	// CertificateInfoValidFrom requests the native notBefore value.
	CertificateInfoValidFrom
	// CertificateInfoValidUntil requests the native notAfter value.
	CertificateInfoValidUntil
	// CertificateInfoIssuer requests the native issuer distinguished name.
	CertificateInfoIssuer
	// CertificateInfoPolicy requests native certificate policy values.
	CertificateInfoPolicy
	// CertificateInfoKeyUsage requests native key usage values.
	CertificateInfoKeyUsage
	// CertificateInfoExtKeyUsage requests native extended key usage values.
	CertificateInfoExtKeyUsage
	// CertificateInfoAuthKeyID requests the authority key identifier.
	CertificateInfoAuthKeyID
	// CertificateInfoSubjKeyID requests the subject key identifier.
	CertificateInfoSubjKeyID
	// CertificateInfoAlgorithmSignCert requests the signature algorithm.
	CertificateInfoAlgorithmSignCert
	// CertificateInfoPublicKey requests the native public key string.
	CertificateInfoPublicKey
	// CertificateInfoOCSPURL requests the OCSP responder URL.
	CertificateInfoOCSPURL
	// CertificateInfoCRLURL requests the CRL distribution point URL.
	CertificateInfoCRLURL
	// CertificateInfoDeltaCRLURL requests the delta CRL distribution point URL.
	CertificateInfoDeltaCRLURL
	// CertificateInfoSubjectCountry requests the subject country value.
	CertificateInfoSubjectCountry
	// CertificateInfoSubjectSerialNumber requests the subject serialNumber value.
	CertificateInfoSubjectSerialNumber
	// CertificateInfoSubjectOrganization requests the subject organization value.
	CertificateInfoSubjectOrganization
	// CertificateInfoSubjectOrganizationalUnit requests the subject organizational unit value.
	CertificateInfoSubjectOrganizationalUnit
)

type CertificateRole added in v0.5.0

type CertificateRole string

CertificateRole identifies known Kazakhstan NCA role policy OIDs.

const (
	// CertificateRolePersonSystem identifies policy OID 1.2.398.3.3.4.1.1.1.
	CertificateRolePersonSystem CertificateRole = kzPolicyPersonSystem
	// CertificateRoleFirstHead identifies policy OID 1.2.398.3.3.4.1.2.1.
	CertificateRoleFirstHead CertificateRole = kzPolicyFirstHead
	// CertificateRoleSigner identifies policy OID 1.2.398.3.3.4.1.2.2.
	CertificateRoleSigner CertificateRole = kzPolicySigner
	// CertificateRoleFinancialSigner identifies policy OID 1.2.398.3.3.4.1.2.3.
	CertificateRoleFinancialSigner CertificateRole = kzPolicyFinancialSigner
	// CertificateRoleHR identifies policy OID 1.2.398.3.3.4.1.2.4.
	CertificateRoleHR CertificateRole = kzPolicyHR
	// CertificateRoleEmployee identifies policy OID 1.2.398.3.3.4.1.2.5.
	CertificateRoleEmployee CertificateRole = kzPolicyEmployee
	// CertificateRoleLegalEntitySystem identifies policy OID 1.2.398.3.3.4.1.2.6.
	CertificateRoleLegalEntitySystem CertificateRole = kzPolicyLegalEntitySystem
)

type CertificateSubjectType added in v0.5.0

type CertificateSubjectType string

CertificateSubjectType identifies known Kazakhstan NCA subject type policy OIDs.

const (
	// CertificateSubjectUnknown means the subject type could not be inferred.
	CertificateSubjectUnknown CertificateSubjectType = ""
	// CertificateSubjectPerson identifies policy OID 1.2.398.3.3.4.1.1.
	CertificateSubjectPerson CertificateSubjectType = kzPolicyPerson
	// CertificateSubjectLegalEntity identifies policy OID 1.2.398.3.3.4.1.2.
	CertificateSubjectLegalEntity CertificateSubjectType = kzPolicyLegalEntity
)

type CertificateTimeCheck

type CertificateTimeCheck int

CertificateTimeCheck controls certificate-time checks performed by KalkanCrypt while verifying signatures or certificate chains.

const (
	// DefaultCertificateTimeCheck keeps KalkanCrypt's default certificate-time
	// validation behavior.
	DefaultCertificateTimeCheck CertificateTimeCheck = iota
	// SkipCertificateTimeCheck sets KC_NOCHECKCERTTIME. It can be useful when
	// verifying signatures according to an external archival policy, but it
	// weakens validation and should be enabled only when that policy explicitly
	// allows it.
	SkipCertificateTimeCheck
)

type CertificateType

type CertificateType int

CertificateType identifies a certificate role in KalkanCrypt's store.

const (
	// CertificateCA marks a root CA certificate.
	CertificateCA CertificateType = iota
	// CertificateIntermediate marks an intermediate CA certificate.
	CertificateIntermediate
	// CertificateUser marks a user certificate.
	CertificateUser
)

type CertificateValidation

type CertificateValidation struct {
	// Info is KalkanCrypt's native validation information string.
	Info string
	// OCSPResponse contains the optional raw OCSP response returned by
	// KalkanCrypt when ReturnOCSPResponse is set.
	OCSPResponse []byte
}

CertificateValidation is returned by ValidateCertificate.

type CertificateValidationMode

type CertificateValidationMode int

CertificateValidationMode selects how KalkanCrypt checks certificate revocation while validating a certificate.

const (
	// CertificateValidationUnspecified is rejected by ValidateCertificate.
	CertificateValidationUnspecified CertificateValidationMode = iota
	// CertificateValidationNone disables external CRL/OCSP validation.
	CertificateValidationNone
	// CertificateValidationCRL validates against a CRL file or directory path.
	CertificateValidationCRL
	// CertificateValidationOCSP validates through an OCSP responder.
	CertificateValidationOCSP
)

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client owns one initialized KalkanCrypt session.

KalkanCrypt stores process-global state inside the native library. The low-level ckalkan package therefore allows one active native client per process and serializes native calls. Client follows that model.

func Open

func Open(ctx context.Context, options ...Option) (*Client, error)

Open loads and initializes KalkanCrypt.

The context is checked before and between Go setup steps and while waiting to enter a native call, including waiting for the native call serialization lock. It cannot interrupt a KalkanCrypt call after control has entered the shared library.

Example
package main

import (
	"context"
	"log"
	"os"

	"github.com/skarm/kalkan"
)

const (
	testTSAURL  = "http://test.pki.gov.kz/tsp/"
	testOCSPURL = "http://test.pki.gov.kz/ocsp/"
)

func main() {
	ctx := context.Background()

	client, err := kalkan.Open(ctx,
		kalkan.WithLibraryPath("/usr/local/lib/libkalkancryptwr-64.so"),
		kalkan.WithTSAURL(testTSAURL),
		kalkan.WithOCSPURL(testOCSPURL),
		kalkan.WithTrustedCertificate(kalkan.TrustedCertificate{
			Path: "/etc/kalkan/certs/root.pem",
			Type: kalkan.CertificateCA,
		}),
	)
	if err != nil {
		log.Fatal(err)
	}

	err = client.LoadKeyStore(ctx, kalkan.KeyStore{
		Type:     kalkan.PKCS12,
		Path:     "/etc/kalkan/keys/signing.p12",
		Password: os.Getenv("KALKAN_KEY_PASSWORD"),
		Alias:    "signing-key",
	})
	if err != nil {
		_ = client.Close()
		log.Fatal(err)
	}
	defer client.Close()
}

func (*Client) Close

func (c *Client) Close() error

Close releases the native KalkanCrypt session. It may be called more than once. Close waits for any in-flight native call to return before closing the native library.

func (*Client) CloseContext added in v0.5.0

func (c *Client) CloseContext(ctx context.Context) error

CloseContext releases the native KalkanCrypt session with context-aware waiting. It may be called more than once.

The context can stop waiting for a close that is queued behind another native call or already running in another goroutine. It cannot interrupt a KalkanCrypt call after control has entered the shared library. Once CloseContext starts closing a client, new operations are rejected even if the caller stops waiting.

func (*Client) ExtractZIPSignerCertificate added in v0.5.0

func (c *Client) ExtractZIPSignerCertificate(ctx context.Context, req ExtractZIPSignerCertificateRequest) ([]byte, error)

ExtractZIPSignerCertificate extracts a signer certificate without verifying the ZIP signature.

Example
package main

import (
	"context"
	"log"
	"os"

	"github.com/skarm/kalkan"
)

const (
	testTSAURL  = "http://test.pki.gov.kz/tsp/"
	testOCSPURL = "http://test.pki.gov.kz/ocsp/"
)

func main() {
	ctx := context.Background()
	client := openExampleClient(ctx)

	certificate, err := client.ExtractZIPSignerCertificate(ctx, kalkan.ExtractZIPSignerCertificateRequest{
		Path: "/data/document.signed.zip",
	})
	if err != nil {
		_ = client.Close()
		log.Fatal(err)
	}
	defer client.Close()

	_ = certificate
}

func openExampleClient(ctx context.Context) *kalkan.Client {
	client, err := kalkan.Open(ctx,
		kalkan.WithLibraryPath("/usr/local/lib/libkalkancryptwr-64.so"),
		kalkan.WithTSAURL(testTSAURL),
		kalkan.WithOCSPURL(testOCSPURL),
	)
	if err != nil {
		log.Fatal(err)
	}

	if err := client.LoadKeyStore(ctx, kalkan.KeyStore{
		Type:     kalkan.PKCS12,
		Path:     "/etc/kalkan/keys/signing.p12",
		Password: os.Getenv("KALKAN_KEY_PASSWORD"),
		Alias:    "signing-key",
	}); err != nil {
		_ = client.Close()
		log.Fatal(err)
	}

	return client
}

func (*Client) GetCertFromCMS

func (c *Client) GetCertFromCMS(ctx context.Context, cms Source) ([]*x509.Certificate, error)

GetCertFromCMS extracts signer certificates embedded in a CMS container.

func (*Client) GetCertFromXML

func (c *Client) GetCertFromXML(ctx context.Context, source Source) ([]*x509.Certificate, error)

GetCertFromXML extracts signer certificates embedded in signed XML.

func (*Client) GetSigAlgFromXML

func (c *Client) GetSigAlgFromXML(ctx context.Context, source Source) (string, error)

GetSigAlgFromXML returns the native XML signature algorithm identifier.

func (*Client) GetTimeFromSig

func (c *Client) GetTimeFromSig(ctx context.Context, signature Source) (time.Time, error)

GetTimeFromSig returns the timestamp embedded in a CMS signature.

func (*Client) Hash

func (c *Client) Hash(ctx context.Context, req HashRequest) (*Digest, error)

Hash calculates a digest using KalkanCrypt.

Example
package main

import (
	"context"
	"log"
	"os"

	"github.com/skarm/kalkan"
)

const (
	testTSAURL  = "http://test.pki.gov.kz/tsp/"
	testOCSPURL = "http://test.pki.gov.kz/ocsp/"
)

func main() {
	ctx := context.Background()
	client := openExampleClient(ctx)

	digest, err := client.Hash(ctx, kalkan.HashRequest{
		Algorithm: kalkan.GOST2015_512,
		Data:      kalkan.File("/data/document.bin"),
	})
	if err != nil {
		_ = client.Close()
		log.Fatal(err)
	}
	defer client.Close()

	_ = digest.Data
}

func openExampleClient(ctx context.Context) *kalkan.Client {
	client, err := kalkan.Open(ctx,
		kalkan.WithLibraryPath("/usr/local/lib/libkalkancryptwr-64.so"),
		kalkan.WithTSAURL(testTSAURL),
		kalkan.WithOCSPURL(testOCSPURL),
	)
	if err != nil {
		log.Fatal(err)
	}

	if err := client.LoadKeyStore(ctx, kalkan.KeyStore{
		Type:     kalkan.PKCS12,
		Path:     "/etc/kalkan/keys/signing.p12",
		Password: os.Getenv("KALKAN_KEY_PASSWORD"),
		Alias:    "signing-key",
	}); err != nil {
		_ = client.Close()
		log.Fatal(err)
	}

	return client
}

func (*Client) LoadKeyStore

func (c *Client) LoadKeyStore(ctx context.Context, store KeyStore) error

LoadKeyStore loads a key container into the native KalkanCrypt session.

func (*Client) LoadTrustedCertificate

func (c *Client) LoadTrustedCertificate(ctx context.Context, cert TrustedCertificate) error

LoadTrustedCertificate loads a certificate into the native KalkanCrypt store.

func (*Client) SetProxy

func (c *Client) SetProxy(ctx context.Context, proxy Proxy) error

SetProxy configures KalkanCrypt's native HTTP proxy for the open session.

func (*Client) SignCMS

func (c *Client) SignCMS(ctx context.Context, req SignCMSRequest) (*CMS, error)

SignCMS signs data and returns CMS output bytes. The default output format is raw DER CMS.

Example
package main

import (
	"context"
	"log"
	"os"

	"github.com/skarm/kalkan"
)

const (
	testTSAURL  = "http://test.pki.gov.kz/tsp/"
	testOCSPURL = "http://test.pki.gov.kz/ocsp/"
)

func main() {
	ctx := context.Background()
	client := openExampleClient(ctx)

	signed, err := client.SignCMS(ctx, kalkan.SignCMSRequest{
		Data:               kalkan.Bytes([]byte("document payload")),
		Detached:           true,
		Timestamp:          true,
		IncludeCertificate: true,
	})
	if err != nil {
		_ = client.Close()
		log.Fatal(err)
	}
	defer client.Close()

	_ = signed.Data
}

func openExampleClient(ctx context.Context) *kalkan.Client {
	client, err := kalkan.Open(ctx,
		kalkan.WithLibraryPath("/usr/local/lib/libkalkancryptwr-64.so"),
		kalkan.WithTSAURL(testTSAURL),
		kalkan.WithOCSPURL(testOCSPURL),
	)
	if err != nil {
		log.Fatal(err)
	}

	if err := client.LoadKeyStore(ctx, kalkan.KeyStore{
		Type:     kalkan.PKCS12,
		Path:     "/etc/kalkan/keys/signing.p12",
		Password: os.Getenv("KALKAN_KEY_PASSWORD"),
		Alias:    "signing-key",
	}); err != nil {
		_ = client.Close()
		log.Fatal(err)
	}

	return client
}

func (*Client) SignHash

func (c *Client) SignHash(ctx context.Context, req SignHashRequest) (*CMS, error)

SignHash signs raw digest bytes and returns CMS output bytes. The default output format is raw DER CMS.

Example
package main

import (
	"context"
	"log"
	"os"

	"github.com/skarm/kalkan"
)

const (
	testTSAURL  = "http://test.pki.gov.kz/tsp/"
	testOCSPURL = "http://test.pki.gov.kz/ocsp/"
)

func main() {
	ctx := context.Background()
	client := openExampleClient(ctx)

	digest, err := client.Hash(ctx, kalkan.HashRequest{
		Algorithm: kalkan.GOST2015_512,
		Data:      kalkan.Bytes([]byte("document payload")),
	})
	if err != nil {
		_ = client.Close()
		log.Fatal(err)
	}

	signed, err := client.SignHash(ctx, kalkan.SignHashRequest{
		Digest:             digest.Data,
		DigestAlgorithm:    digest.Algorithm,
		IncludeCertificate: true,
	})
	if err != nil {
		_ = client.Close()
		log.Fatal(err)
	}
	defer client.Close()

	_ = signed.Data
}

func openExampleClient(ctx context.Context) *kalkan.Client {
	client, err := kalkan.Open(ctx,
		kalkan.WithLibraryPath("/usr/local/lib/libkalkancryptwr-64.so"),
		kalkan.WithTSAURL(testTSAURL),
		kalkan.WithOCSPURL(testOCSPURL),
	)
	if err != nil {
		log.Fatal(err)
	}

	if err := client.LoadKeyStore(ctx, kalkan.KeyStore{
		Type:     kalkan.PKCS12,
		Path:     "/etc/kalkan/keys/signing.p12",
		Password: os.Getenv("KALKAN_KEY_PASSWORD"),
		Alias:    "signing-key",
	}); err != nil {
		_ = client.Close()
		log.Fatal(err)
	}

	return client
}

func (*Client) SignWSSE

func (c *Client) SignWSSE(ctx context.Context, req SignWSSERequest) (*SignedXML, error)

SignWSSE signs a SOAP/WS-Security document.

Example
package main

import (
	"context"
	"log"
	"os"

	"github.com/skarm/kalkan"
)

const (
	testTSAURL  = "http://test.pki.gov.kz/tsp/"
	testOCSPURL = "http://test.pki.gov.kz/ocsp/"
)

func main() {
	ctx := context.Background()
	client := openExampleClient(ctx)

	signed, err := client.SignWSSE(ctx, kalkan.SignWSSERequest{
		XML:              kalkan.Bytes([]byte(`<m:GetData xmlns:m="urn:example"/>`)),
		BodyID:           "TheBody",
		WrapSOAP:         true,
		Canonicalization: kalkan.XMLCanonicalizationInclusive,
	})
	if err != nil {
		_ = client.Close()
		log.Fatal(err)
	}
	defer client.Close()

	_ = signed.XML
}

func openExampleClient(ctx context.Context) *kalkan.Client {
	client, err := kalkan.Open(ctx,
		kalkan.WithLibraryPath("/usr/local/lib/libkalkancryptwr-64.so"),
		kalkan.WithTSAURL(testTSAURL),
		kalkan.WithOCSPURL(testOCSPURL),
	)
	if err != nil {
		log.Fatal(err)
	}

	if err := client.LoadKeyStore(ctx, kalkan.KeyStore{
		Type:     kalkan.PKCS12,
		Path:     "/etc/kalkan/keys/signing.p12",
		Password: os.Getenv("KALKAN_KEY_PASSWORD"),
		Alias:    "signing-key",
	}); err != nil {
		_ = client.Close()
		log.Fatal(err)
	}

	return client
}

func (*Client) SignXML

func (c *Client) SignXML(ctx context.Context, req SignXMLRequest) (*SignedXML, error)

SignXML signs an XML document.

Example
package main

import (
	"context"
	"log"
	"os"

	"github.com/skarm/kalkan"
)

const (
	testTSAURL  = "http://test.pki.gov.kz/tsp/"
	testOCSPURL = "http://test.pki.gov.kz/ocsp/"
)

func main() {
	ctx := context.Background()
	client := openExampleClient(ctx)

	signed, err := client.SignXML(ctx, kalkan.SignXMLRequest{
		XML:              kalkan.Bytes([]byte(`<root><value>data</value></root>`)),
		Canonicalization: kalkan.XMLCanonicalizationInclusive,
	})
	if err != nil {
		_ = client.Close()
		log.Fatal(err)
	}
	defer client.Close()

	_ = signed.XML
}

func openExampleClient(ctx context.Context) *kalkan.Client {
	client, err := kalkan.Open(ctx,
		kalkan.WithLibraryPath("/usr/local/lib/libkalkancryptwr-64.so"),
		kalkan.WithTSAURL(testTSAURL),
		kalkan.WithOCSPURL(testOCSPURL),
	)
	if err != nil {
		log.Fatal(err)
	}

	if err := client.LoadKeyStore(ctx, kalkan.KeyStore{
		Type:     kalkan.PKCS12,
		Path:     "/etc/kalkan/keys/signing.p12",
		Password: os.Getenv("KALKAN_KEY_PASSWORD"),
		Alias:    "signing-key",
	}); err != nil {
		_ = client.Close()
		log.Fatal(err)
	}

	return client
}

func (*Client) SignZIP

func (c *Client) SignZIP(ctx context.Context, req SignZIPRequest) (*SignedZIP, error)

SignZIP signs InputPath and creates a KalkanCrypt ZIP container at OutputPath.

Example
package main

import (
	"context"
	"log"
	"os"
	"path/filepath"

	"github.com/skarm/kalkan"
)

const (
	testTSAURL  = "http://test.pki.gov.kz/tsp/"
	testOCSPURL = "http://test.pki.gov.kz/ocsp/"
)

func main() {
	ctx := context.Background()
	client := openExampleClient(ctx)

	outputDir, err := os.MkdirTemp("", "kalkan-signzip-*")
	if err != nil {
		_ = client.Close()
		log.Fatal(err)
	}
	cleanupOutputDir := func() {
		_ = os.RemoveAll(outputDir)
	}

	if err := os.Chmod(outputDir, 0o700); err != nil {
		cleanupOutputDir()
		_ = client.Close()
		log.Fatal(err)
	}

	signed, err := client.SignZIP(ctx, kalkan.SignZIPRequest{
		InputPath:  "/data/document.bin",
		OutputPath: filepath.Join(outputDir, "document.signed.zip"),
	})
	if err != nil {
		cleanupOutputDir()
		_ = client.Close()
		log.Fatal(err)
	}
	defer cleanupOutputDir()
	defer client.Close()

	_ = signed.Path
}

func openExampleClient(ctx context.Context) *kalkan.Client {
	client, err := kalkan.Open(ctx,
		kalkan.WithLibraryPath("/usr/local/lib/libkalkancryptwr-64.so"),
		kalkan.WithTSAURL(testTSAURL),
		kalkan.WithOCSPURL(testOCSPURL),
	)
	if err != nil {
		log.Fatal(err)
	}

	if err := client.LoadKeyStore(ctx, kalkan.KeyStore{
		Type:     kalkan.PKCS12,
		Path:     "/etc/kalkan/keys/signing.p12",
		Password: os.Getenv("KALKAN_KEY_PASSWORD"),
		Alias:    "signing-key",
	}); err != nil {
		_ = client.Close()
		log.Fatal(err)
	}

	return client
}

func (*Client) ValidateCertificate

func (c *Client) ValidateCertificate(ctx context.Context, req ValidateCertificateRequest) (*CertificateValidation, error)

ValidateCertificate validates a certificate through KalkanCrypt.

Example
package main

import (
	"context"
	"log"
	"os"

	"github.com/skarm/kalkan"
)

const (
	testTSAURL  = "http://test.pki.gov.kz/tsp/"
	testOCSPURL = "http://test.pki.gov.kz/ocsp/"
)

func main() {
	ctx := context.Background()
	client := openExampleClient(ctx)

	certPEM, err := os.ReadFile("/etc/kalkan/certs/user.pem")
	if err != nil {
		_ = client.Close()
		log.Fatal(err)
	}

	validation, err := client.ValidateCertificate(ctx, kalkan.ValidateCertificateRequest{
		Certificate:        kalkan.PEM(certPEM),
		Mode:               kalkan.CertificateValidationOCSP,
		ReturnOCSPResponse: true,
	})
	if err != nil {
		_ = client.Close()
		log.Fatal(err)
	}
	defer client.Close()

	_ = validation.OCSPResponse
}

func openExampleClient(ctx context.Context) *kalkan.Client {
	client, err := kalkan.Open(ctx,
		kalkan.WithLibraryPath("/usr/local/lib/libkalkancryptwr-64.so"),
		kalkan.WithTSAURL(testTSAURL),
		kalkan.WithOCSPURL(testOCSPURL),
	)
	if err != nil {
		log.Fatal(err)
	}

	if err := client.LoadKeyStore(ctx, kalkan.KeyStore{
		Type:     kalkan.PKCS12,
		Path:     "/etc/kalkan/keys/signing.p12",
		Password: os.Getenv("KALKAN_KEY_PASSWORD"),
		Alias:    "signing-key",
	}); err != nil {
		_ = client.Close()
		log.Fatal(err)
	}

	return client
}

func (*Client) VerifyCMS

func (c *Client) VerifyCMS(ctx context.Context, req VerifyCMSRequest) (*Verification, error)

VerifyCMS verifies an attached or detached CMS signature.

Example
package main

import (
	"context"
	"log"
	"os"

	"github.com/skarm/kalkan"
)

const (
	testTSAURL  = "http://test.pki.gov.kz/tsp/"
	testOCSPURL = "http://test.pki.gov.kz/ocsp/"
)

func main() {
	ctx := context.Background()
	client := openExampleClient(ctx)

	verification, err := client.VerifyCMS(ctx, kalkan.VerifyCMSRequest{
		Signature: kalkan.File("/data/signature.cms").WithEncoding(kalkan.EncodingDER),
		Data:      kalkan.File("/data/document.bin"),
		Detached:  true,
	})
	if err != nil {
		_ = client.Close()
		log.Fatal(err)
	}
	defer client.Close()

	_ = verification.SignerCert
}

func openExampleClient(ctx context.Context) *kalkan.Client {
	client, err := kalkan.Open(ctx,
		kalkan.WithLibraryPath("/usr/local/lib/libkalkancryptwr-64.so"),
		kalkan.WithTSAURL(testTSAURL),
		kalkan.WithOCSPURL(testOCSPURL),
	)
	if err != nil {
		log.Fatal(err)
	}

	if err := client.LoadKeyStore(ctx, kalkan.KeyStore{
		Type:     kalkan.PKCS12,
		Path:     "/etc/kalkan/keys/signing.p12",
		Password: os.Getenv("KALKAN_KEY_PASSWORD"),
		Alias:    "signing-key",
	}); err != nil {
		_ = client.Close()
		log.Fatal(err)
	}

	return client
}

func (*Client) VerifyXML

func (c *Client) VerifyXML(ctx context.Context, req VerifyXMLRequest) (*Verification, error)

VerifyXML verifies a signed XML document.

func (*Client) VerifyZIP

func (c *Client) VerifyZIP(ctx context.Context, req VerifyZIPRequest) (*Verification, error)

VerifyZIP verifies a KalkanCrypt ZIP container.

Example
package main

import (
	"context"
	"log"
	"os"

	"github.com/skarm/kalkan"
)

const (
	testTSAURL  = "http://test.pki.gov.kz/tsp/"
	testOCSPURL = "http://test.pki.gov.kz/ocsp/"
)

func main() {
	ctx := context.Background()
	client := openExampleClient(ctx)

	verification, err := client.VerifyZIP(ctx, kalkan.VerifyZIPRequest{
		Path: "/data/document.signed.zip",
	})
	if err != nil {
		_ = client.Close()
		log.Fatal(err)
	}
	defer client.Close()

	_ = verification.Info
}

func openExampleClient(ctx context.Context) *kalkan.Client {
	client, err := kalkan.Open(ctx,
		kalkan.WithLibraryPath("/usr/local/lib/libkalkancryptwr-64.so"),
		kalkan.WithTSAURL(testTSAURL),
		kalkan.WithOCSPURL(testOCSPURL),
	)
	if err != nil {
		log.Fatal(err)
	}

	if err := client.LoadKeyStore(ctx, kalkan.KeyStore{
		Type:     kalkan.PKCS12,
		Path:     "/etc/kalkan/keys/signing.p12",
		Password: os.Getenv("KALKAN_KEY_PASSWORD"),
		Alias:    "signing-key",
	}); err != nil {
		_ = client.Close()
		log.Fatal(err)
	}

	return client
}

func (*Client) X509CertificateGetInfo

func (c *Client) X509CertificateGetInfo(ctx context.Context, cert *x509.Certificate) (*CertificateInfo, error)

X509CertificateGetInfo collects commonly used certificate properties through KalkanCrypt's native X509CertificateGetInfo calls.

func (*Client) X509CertificateGetInfoFields

func (c *Client) X509CertificateGetInfoFields(ctx context.Context, cert *x509.Certificate, fields CertificateInfoField) (*CertificateInfo, error)

X509CertificateGetInfoFields collects selected certificate properties through KalkanCrypt's native X509CertificateGetInfo calls.

func (*Client) X509ExportCertificateFromStore

func (c *Client) X509ExportCertificateFromStore(ctx context.Context) (*x509.Certificate, error)

X509ExportCertificateFromStore exports the default certificate from KalkanCrypt's native store and parses it as an x509 certificate.

type Digest

type Digest struct {
	// Algorithm is the algorithm used to calculate Data.
	Algorithm HashAlgorithm
	// Data contains the raw digest bytes.
	Data []byte
}

Digest is returned by Hash.

type Encoding

type Encoding int

Encoding describes how bytes or file contents are encoded before KalkanCrypt reads them.

const (
	// EncodingAuto lets the operation choose the field-specific default.
	// For example, VerifyCMS treats raw CMS bytes as DER CMS input.
	EncodingAuto Encoding = iota
	// EncodingRaw means the source is plain binary/text data. Operations may
	// map raw data to the native flag that represents their raw format, such as
	// DER for CMS signatures.
	EncodingRaw
	// EncodingBase64 means the source is already base64 text.
	EncodingBase64
	// EncodingPEM means the source is PEM text.
	EncodingPEM
	// EncodingDER means the source is DER binary data.
	EncodingDER
)

type ExtractZIPSignerCertificateRequest added in v0.5.0

type ExtractZIPSignerCertificateRequest struct {
	// Path is passed unchanged to KalkanCrypt. Keep the referenced file unchanged
	// until ExtractZIPSignerCertificate returns.
	Path string
	// SignerID selects a signer certificate from multi-signer containers.
	SignerID int
	// CertificateTimeCheck controls KalkanCrypt certificate-time validation.
	CertificateTimeCheck CertificateTimeCheck
}

ExtractZIPSignerCertificateRequest describes signer-certificate extraction from a ZIP container.

type HashAlgorithm

type HashAlgorithm int

HashAlgorithm selects the digest algorithm used by Hash.

const (
	// SHA256 calculates a SHA-256 digest.
	SHA256 HashAlgorithm = iota
	// GOST95 calculates a GOST R 34.11-95 digest.
	GOST95
	// GOST2015_256 calculates a GOST R 34.11-2015 256-bit digest.
	GOST2015_256
	// GOST2015_512 calculates a GOST R 34.11-2015 512-bit digest.
	GOST2015_512
)

type HashRequest

type HashRequest struct {
	// Algorithm selects the digest algorithm. The zero value is SHA256.
	Algorithm HashAlgorithm
	// Data is the input data. File sources are passed to KalkanCrypt as file
	// paths when the native library supports KC_IN_FILE for HashData.
	Data Source
}

HashRequest describes data to hash.

type KeyStore

type KeyStore struct {
	// Type selects the storage provider.
	Type KeyStoreType
	// Path is the native container path.
	Path string
	// Password is the container password.
	Password string
	// Alias optionally selects a key alias inside the container.
	Alias string
}

KeyStore describes a private-key container to load into KalkanCrypt.

type KeyStoreType

type KeyStoreType int

KeyStoreType identifies a KalkanCrypt key storage provider.

const (
	// PKCS12 loads a file-system PKCS#12 container.
	PKCS12 KeyStoreType = iota
)

type Option

type Option func(*config)

Option configures Open.

func WithLibraryPath

func WithLibraryPath(path string) Option

WithLibraryPath sets the absolute KalkanCrypt shared-library path.

func WithLogger

func WithLogger(logger *slog.Logger) Option

WithLogger enables diagnostic structured logging for Client operations. Passing nil leaves logging disabled. The logger receives a component=kalkan attribute and is never installed as slog's process-global default logger.

func WithMaxInputSize

func WithMaxInputSize(size int64) Option

WithMaxInputSize sets a byte limit for high-level in-memory byte inputs before native calls. Values less than or equal to zero make memory inputs unlimited.

func WithMaxOutputBufferSize

func WithMaxOutputBufferSize(size int) Option

WithMaxOutputBufferSize sets the hard cap for the low-level KalkanCrypt output-buffer retry policy. Zero restores DefaultMaxOutputBufferSize. A positive value selects a smaller or larger cap, subject to the native C int ABI maximum. A negative value makes Open return ErrInvalidInput.

func WithOCSPURL

func WithOCSPURL(url string) Option

WithOCSPURL overrides the OCSP endpoint used by ValidateCertificate when the request does not specify RevocationSource.

func WithProxy

func WithProxy(proxy Proxy) Option

WithProxy configures KalkanCrypt's native HTTP proxy settings during Open.

func WithTSAURL

func WithTSAURL(url string) Option

WithTSAURL overrides the timestamp authority endpoint.

func WithTrustedCertificate

func WithTrustedCertificate(cert TrustedCertificate) Option

WithTrustedCertificate loads a trusted certificate during Open.

type Proxy

type Proxy struct {
	// Enabled enables or disables proxy use.
	Enabled bool
	// Address is the proxy host or IP address.
	Address string
	// Port is the proxy port.
	Port string
	// User is the optional proxy username.
	User string
	// Password is the optional proxy password.
	Password string
}

Proxy configures KalkanCrypt's native HTTP proxy.

type SignCMSRequest

type SignCMSRequest struct {
	// Alias selects a loaded key alias. Empty alias lets KalkanCrypt use its
	// default loaded key when the native library supports that behavior.
	Alias string
	// Data is the payload to sign. The zero-value Source is rejected; use
	// Bytes(nil) or Bytes([]byte{}) only when an explicit empty payload is
	// intended.
	Data Source
	// Detached requests a detached CMS signature.
	Detached bool
	// Timestamp requests a TSA timestamp token.
	Timestamp bool
	// IncludeCertificate asks KalkanCrypt to embed the signing certificate in
	// the CMS container.
	IncludeCertificate bool
	// OutputFormat selects the CMS output representation. The zero value
	// returns raw DER CMS bytes.
	OutputFormat CMSOutputFormat
	// CertificateTimeCheck controls KalkanCrypt certificate-time validation while
	// building the signature.
	CertificateTimeCheck CertificateTimeCheck
}

SignCMSRequest describes CMS signing input.

type SignHashRequest

type SignHashRequest struct {
	// Alias selects a loaded key alias. Empty alias lets KalkanCrypt use its
	// default loaded key when the native library supports that behavior.
	Alias string
	// Digest contains the precomputed raw digest bytes to sign, not the original
	// payload.
	Digest []byte
	// DigestAlgorithm selects the algorithm that produced Digest. The zero value
	// is SHA256. Set it explicitly when signing GOST or other non-SHA256 digests
	// so the wrapper can reject length mismatches before native calls.
	DigestAlgorithm HashAlgorithm
	// Timestamp requests a TSA timestamp token.
	Timestamp bool
	// IncludeCertificate asks KalkanCrypt to embed the signing certificate in
	// the CMS container.
	IncludeCertificate bool
	// OutputFormat selects the CMS output representation. The zero value
	// returns raw DER CMS bytes.
	OutputFormat CMSOutputFormat
	// CertificateTimeCheck controls KalkanCrypt certificate-time validation while
	// signing the digest.
	CertificateTimeCheck CertificateTimeCheck
}

SignHashRequest describes signing of an already calculated digest.

type SignWSSERequest

type SignWSSERequest struct {
	// Alias selects a loaded key alias.
	Alias string
	// XML is either a full SOAP envelope or a payload that should be wrapped when
	// WrapSOAP is true.
	XML Source
	// BodyID is the wsu:Id value of the SOAP Body that KalkanCrypt signs. It
	// is required whether XML is wrapped by this package or supplied as a full
	// SOAP envelope.
	BodyID string
	// WrapSOAP wraps XML into a minimal SOAP envelope before signing.
	WrapSOAP bool
	// Canonicalization selects the XML canonicalization algorithm.
	Canonicalization XMLCanonicalization
	// CertificateTimeCheck controls certificate-time validation.
	CertificateTimeCheck CertificateTimeCheck
}

SignWSSERequest describes WS-Security XML signing input.

type SignXMLRequest

type SignXMLRequest struct {
	// Alias selects a loaded key alias.
	Alias string
	// XML is the XML document to sign.
	XML Source
	// SignNodeID is the XML node id passed to KalkanCrypt.
	SignNodeID string
	// ParentSignNode is the parent signature node name passed to KalkanCrypt.
	ParentSignNode string
	// ParentNamespace is the parent signature namespace passed to KalkanCrypt.
	ParentNamespace string
	// Canonicalization selects the XML canonicalization algorithm.
	Canonicalization XMLCanonicalization
	// CertificateTimeCheck controls certificate-time validation.
	CertificateTimeCheck CertificateTimeCheck
}

SignXMLRequest describes XML signing input.

type SignZIPRequest

type SignZIPRequest struct {
	// Alias selects a loaded key alias. Empty alias lets KalkanCrypt use its
	// default loaded key when the native library supports that behavior.
	Alias string
	// InputPath is passed unchanged to KalkanCrypt. Keep the referenced file
	// unchanged until SignZIP returns.
	InputPath string
	// OutputPath is the expected ZIP container path and must end with .zip,
	// matched case-insensitively. KalkanCrypt creates lowercase .zip output, so
	// non-lowercase extensions are accepted but SignedZIP.Path reports the
	// actual lowercase path.
	// The path must not exist. KalkanCrypt creates it without an atomic
	// create-if-absent guarantee.
	OutputPath string
	// CertificateTimeCheck controls KalkanCrypt certificate-time validation while
	// building the ZIP signature.
	CertificateTimeCheck CertificateTimeCheck
}

SignZIPRequest describes signing a file into a KalkanCrypt ZIP container.

type SignedXML

type SignedXML struct {
	// XML contains the signed XML document.
	XML []byte
}

SignedXML is returned by SignXML and SignWSSE.

type SignedZIP

type SignedZIP struct {
	// Path is the ZIP container path created by KalkanCrypt.
	Path string
}

SignedZIP is returned by SignZIP.

type Source

type Source struct {
	// contains filtered or unexported fields
}

Source is an operation input that can be either in-memory bytes or a file path. File sources allow KalkanCrypt to read large detached payloads directly when the native function supports KC_IN_FILE. The zero-value Source means "not provided"; constructor-created empty byte sources represent explicit empty input and are validated by each operation's own rules.

func Base64

func Base64(data []byte) Source

Base64 returns an in-memory source that already contains base64 text.

func Bytes

func Bytes(data []byte) Source

Bytes returns an in-memory raw source. Use File for large payloads that KalkanCrypt should read directly.

func DER

func DER(data []byte) Source

DER returns an in-memory DER source.

func File

func File(path string) Source

File returns a file-path source. Empty paths and embedded NUL bytes are rejected by operations before native calls.

func PEM

func PEM(data []byte) Source

PEM returns an in-memory PEM source.

func (Source) WithEncoding

func (s Source) WithEncoding(encoding Encoding) Source

WithEncoding returns a copy of the source with an explicit encoding.

type TrustedCertificate

type TrustedCertificate struct {
	// Data contains certificate bytes when Path is empty.
	Data []byte
	// Path is loaded directly by KalkanCrypt when set.
	Path string
	// Type selects CA, intermediate, or user certificate role.
	Type CertificateType
	// Format selects PEM, DER, or base64 bytes for Data.
	Format CertificateFormat
}

TrustedCertificate describes a certificate loaded into KalkanCrypt's trust store.

type ValidateCertificateRequest

type ValidateCertificateRequest struct {
	// Certificate is the certificate to validate. File sources are unsupported;
	// PEM and base64 are decoded to DER, while raw, auto, and DER are passed
	// unchanged.
	Certificate Source
	// Mode selects the revocation check. The zero value is invalid.
	Mode CertificateValidationMode
	// RevocationSource is a CRL path or OCSP URL. An empty OCSP source uses the
	// configured OCSP URL.
	RevocationSource string
	// CheckTime is the validation time. Zero lets KalkanCrypt use its own
	// default behavior.
	CheckTime time.Time
	// ReturnOCSPResponse requests the raw OCSP response from KalkanCrypt.
	ReturnOCSPResponse bool
	// CertificateTimeCheck controls KalkanCrypt certificate-time validation.
	CertificateTimeCheck CertificateTimeCheck
}

ValidateCertificateRequest describes certificate validation input.

type Verification

type Verification struct {
	// Info is KalkanCrypt's native verification information string.
	Info string
	// Data contains attached CMS payload data when KalkanCrypt returns it. XML
	// and ZIP verification leave it empty.
	Data []byte
	// SignerCert contains the selected signer certificate when KalkanCrypt
	// returns it. XML and ZIP verification leave it empty.
	SignerCert []byte
}

Verification is returned by CMS, XML, and ZIP verification operations.

type VerifyCMSRequest

type VerifyCMSRequest struct {
	// Alias is forwarded to KalkanCrypt's VerifyData alias parameter.
	Alias string
	// Signature is the CMS/signature input. Use File for large signatures or
	// Bytes for in-memory raw CMS bytes.
	Signature Source
	// Data is the detached payload. It is valid only when Detached is true and
	// must be an in-memory source: KalkanCrypt's KC_IN_FILE flag applies to the
	// CMS signature input during verification. For detached verification the
	// zero-value Source is rejected; Bytes(nil) or Bytes([]byte{}) means an
	// explicit empty detached payload.
	Data Source
	// Detached verifies a detached CMS signature.
	Detached bool
	// Encoding describes the signature encoding when Signature does not specify
	// one explicitly. It is most important for File sources because Go does not
	// inspect file contents.
	Encoding Encoding
	// SignerID selects a signer certificate from multi-signer data.
	SignerID int
	// CertificateTimeCheck controls KalkanCrypt certificate-time validation.
	CertificateTimeCheck CertificateTimeCheck
}

VerifyCMSRequest describes CMS verification input.

type VerifyXMLRequest

type VerifyXMLRequest struct {
	// Alias is forwarded to KalkanCrypt's VerifyXML alias parameter.
	Alias string
	// XML is the signed XML document to verify.
	XML Source
	// ExpectedBodyID binds verification to a SOAP Body wsu:Id. It is required for
	// SOAP 1.1 and SOAP 1.2 and must be empty for non-SOAP XML.
	ExpectedBodyID string
	// Canonicalization selects the XML canonicalization algorithm.
	Canonicalization XMLCanonicalization
	// CertificateTimeCheck controls certificate-time validation.
	CertificateTimeCheck CertificateTimeCheck
}

VerifyXMLRequest describes XML verification input.

type VerifyZIPRequest

type VerifyZIPRequest struct {
	// Path is passed unchanged to KalkanCrypt. Keep the referenced file unchanged
	// until VerifyZIP returns.
	Path string
	// CertificateTimeCheck controls KalkanCrypt certificate-time validation.
	CertificateTimeCheck CertificateTimeCheck
}

VerifyZIPRequest describes ZIP signature verification.

type XMLCanonicalization

type XMLCanonicalization int

XMLCanonicalization selects the XML canonicalization algorithm passed to KalkanCrypt. The zero value selects XMLCanonicalizationInclusive.

const (
	// XMLCanonicalizationInclusive selects inclusive XML canonicalization.
	XMLCanonicalizationInclusive XMLCanonicalization = iota
	// XMLCanonicalizationInclusiveWithComments selects inclusive XML
	// canonicalization and preserves comments.
	XMLCanonicalizationInclusiveWithComments
	// XMLCanonicalizationInclusive11 selects inclusive XML canonicalization 1.1.
	XMLCanonicalizationInclusive11
	// XMLCanonicalizationInclusive11WithComments selects inclusive XML
	// canonicalization 1.1 and preserves comments.
	XMLCanonicalizationInclusive11WithComments
	// XMLCanonicalizationExclusive selects exclusive XML canonicalization.
	XMLCanonicalizationExclusive
	// XMLCanonicalizationExclusiveWithComments selects exclusive XML
	// canonicalization and preserves comments.
	XMLCanonicalizationExclusiveWithComments
)

Directories

Path Synopsis
Package ckalkan provides a low-level Go binding for libkalkancryptwr.
Package ckalkan provides a low-level Go binding for libkalkancryptwr.
internal/kalkancrypt
Package kalkancrypt contains the private KalkanCrypt ABI boundary.
Package kalkancrypt contains the private KalkanCrypt ABI boundary.

Jump to

Keyboard shortcuts

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