Пакет 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/C/Linux/C
. Команда для копирования:
sudo cp -f libkalkancryptwr-64.so libkalkancryptwr-64.so.1.1.0 /usr/lib/
Скопировать папку SDK/C/Linux/libs_for_linux/kalkancrypt
в /opt/
:
sudo cp -r kalkancrypt /opt/
sudo chmod -R 555 /opt/kalkancrypt
При использовании gokalkan
убедитесь, что экспортирована переменная окружения:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/kalkancrypt/:/opt/kalkancrypt/lib/engines
Эта переменная нужна для обращения к библиотеке KalkanCrypt.
Версия 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.