Пакет gokalkan
является оберткой над нативными методами библиотеки KalkanCrypt.
KalkanCrypt является основной библиотекой для работы с ЭЦП ключами от pki.gov.kz и позволяет подписывать, верифицировать, вытаскивать данные и много чего другого связанного с электронными подписями, цифровыми сертификатами и ключами.
Особенности пакета gokalkan
:
- Поддержка мультипоточности
- Без зависимостей
- Чистый код
- Напрямую вызывает нативные методы KalkanCrypt
Чтобы использовать библиотеку требуется провести подготовку:
Обратиться в pki.gov.kz чтобы получить SDK. SDK представляет из себя набор библиотек для Java и C.
Сертификаты лежат по пути SDK/C/Linux/ca-certs/Ubuntu
. В папке находятся два типа сертификатов - production
и test
. Для их установки приготовлены скрипты в той же директории. При запуске понадобятся sudo права.
Файлы лежат в директории SDK 2.0/C/Linux/C/libs/v2.0.4
. Команда для копирования:
sudo cp -f libkalkancryptwr-64.so.2.0.4 /usr/lib/libkalkancryptwr-64.so
Версия Go 1.17+
go get github.com/gokalkan/gokalkan
Загрузка хранилища с ключом и сертификатом (например ЭЦП ключ, который начинается с RSA...
):
package main
import (
"fmt"
"log"
"github.com/gokalkan/gokalkan"
)
var (
certPath = "test_cert/GOSTKNCA.p12" // путь к хранилищу
certPassword = "Qwerty12" // пароль
// P.S. никогда не храните пароли в коде
)
func main() {
// для теста
opts := gokalkan.OptsTest
// для прода
// opts := gokalkan.OptsProd
cli, err := gokalkan.NewClient(opts...)
if err != nil {
log.Fatal("new kalkan client create error", err)
}
// Обязательно закрывайте клиент, иначе приведет к утечкам ресурсов
defer cli.Close()
// Подгружаем хранилище с паролем
err = cli.LoadKeyStore(certPath, certPassword)
if err != nil {
log.Fatal("load key store error", err)
}
}
Следует отметить, что при инициализации gokalkan клиента нужно указывать опцию.
Есть две опции - OptsTest
и OptsProd
. Нужно выбрать одну из них в зависимости от окружения.
Для того чтобы подписать XML документ, нужно передать документ в виде строки:
signedXML, err := cli.SignXML("<root>GoKalkan</root>")
fmt.Println("Подписанный XML", signedXML)
fmt.Println("Ошибка", err)
Проверка подписи документа вернет ошибку, если документ подписан неверно либо срок у сертификата с которым подписан истёк.
serial, err := cli.VerifyXML(signedXML)
fmt.Println("Серийный номер", serial)
fmt.Println("Ошибка", err)
Для того чтобы подписать XML документ в формате SignWSSE, нужно передать документ в виде строки
и id для SOAP Body. Функция обернет документ в soap:Envelope
и запишет внутри soap:Body
.
signedXML, err := cli.SignWSSE("<root>gokalkan</root>", "12345")
fmt.Println("Подписанный XML в формате WSSE", signedXML)
fmt.Println("Ошибка", err)
Команда запуска бенчмарка:
go test -bench SignXML -run=^$ -benchmem
Характеристики хост машины:
- goos: linux
- goarch: amd64
- cpu: Intel(R) Core(TM) i5-8500 CPU @ 3.00GHz
Бенчмарк | Кол-во циклов | Средн. время выполнения | Средн. потребление ОЗУ | Средн. кол-во аллокаций |
---|---|---|---|---|
BenchmarkSignXML-6 | 2809 | 422310 ns/op | 2792 B/op | 8 allocs/op |
Zulbukharov Abylaikhan |
Tlekbai Ali |
Kilibayev Azat |
The MIT License (MIT) 2021 - Abylaikhan Zulbukharov.
Please have a look at the LICENSE.md for more details.