func (sig *Signature) Verify(message []byte, signature []byte,
	publicKey []byte) (bool, error) {
	if len(publicKey) != sig.algDetails.LengthPublicKey {
		return false, errors.New("incorrect public key length")
	}
	if len(signature) > sig.algDetails.MaxLengthSignature {
		return false, errors.New("incorrect signature size")
	}
	rv := C.OQS_SIG_verify(sig.sig, (*C.uint8_t)(unsafe.Pointer(&message[0])),
		C.size_t(len(message)), (*C.uint8_t)(unsafe.Pointer(&signature[0])),
		C.size_t(len(signature)), (*C.uint8_t)(unsafe.Pointer(&publicKey[0])))
	if rv != C.OQS_SUCCESS {
		return false, nil
	}
	return true, nil
}
Verify verifies the validity of a signed message, returning true if the
signature is valid, and false otherwise.
package oqs  
import "C"
import (
	"errors"
	"fmt"
	"unsafe"
)
func MemCleanse(v []byte) {
	C.OQS_MEM_cleanse(unsafe.Pointer(&v[0]), C.size_t(len(v)))
}
var enabledKEMs []string
var supportedKEMs []string
func MaxNumberKEMs() int {
	return int(C.OQS_KEM_alg_count())
}
func IsKEMEnabled(algName string) bool {
	result := C.OQS_KEM_alg_is_enabled(C.CString(algName))
	return result != 0
}
func IsKEMSupported(algName string) bool {
	for i := range supportedKEMs {
		if supportedKEMs[i] == algName {
			return true
		}
	}
	return false
}
func KEMName(algID int) (string, error) {
	if algID >= MaxNumberKEMs() {
		return "", errors.New("algorithm ID out of range")
	}
	return C.GoString(C.OQS_KEM_alg_identifier(C.size_t(algID))), nil
}
func SupportedKEMs() []string {
	return supportedKEMs
}
func EnabledKEMs() []string {
	return enabledKEMs
}
func init() {
	C.OQS_init()
	for i := 0; i < MaxNumberKEMs(); i++ {
		KEMName, _ := KEMName(i)
		supportedKEMs = append(supportedKEMs, KEMName)
		if IsKEMEnabled(KEMName) {
			enabledKEMs = append(enabledKEMs, KEMName)
		}
	}
}
type KeyEncapsulationDetails struct {
	ClaimedNISTLevel   int
	IsINDCCA           bool
	LengthCiphertext   int
	LengthPublicKey    int
	LengthSecretKey    int
	LengthSharedSecret int
	Name               string
	Version            string
}
func (kemDetails KeyEncapsulationDetails) String() string {
	return fmt.Sprintf("Name: %s\nVersion: %s\nClaimed NIST level: %d\n"+
		"Is IND_CCA: %v\nLength public key (bytes): %d\nLength secret key ("+
		"bytes): %d\nLength ciphertext (bytes): %d\nLength shared secret ("+
		"bytes): %d", kemDetails.Name,
		kemDetails.Version, kemDetails.ClaimedNISTLevel, kemDetails.IsINDCCA,
		kemDetails.LengthPublicKey, kemDetails.LengthSecretKey,
		kemDetails.LengthCiphertext, kemDetails.LengthSharedSecret)
}
type KeyEncapsulation struct {
	kem        *C.OQS_KEM
	secretKey  []byte
	algDetails KeyEncapsulationDetails
}
func (kem KeyEncapsulation) String() string {
	return fmt.Sprintf("Key encapsulation mechanism: %s",
		kem.algDetails.Name)
}
func (kem *KeyEncapsulation) Init(algName string, secretKey []byte) error {
	if !IsKEMEnabled(algName) {
		if IsKEMSupported(algName) {
			return errors.New(`"` + algName + `" KEM is not enabled by OQS`)
		}
		return errors.New(`"` + algName + `" KEM is not supported by OQS`)
	}
	kem.kem = C.OQS_KEM_new(C.CString(algName))
	kem.secretKey = secretKey
	kem.algDetails.Name = C.GoString(kem.kem.method_name)
	kem.algDetails.Version = C.GoString(kem.kem.alg_version)
	kem.algDetails.ClaimedNISTLevel = int(kem.kem.claimed_nist_level)
	kem.algDetails.IsINDCCA = bool(kem.kem.ind_cca)
	kem.algDetails.LengthPublicKey = int(kem.kem.length_public_key)
	kem.algDetails.LengthSecretKey = int(kem.kem.length_secret_key)
	kem.algDetails.LengthCiphertext = int(kem.kem.length_ciphertext)
	kem.algDetails.LengthSharedSecret = int(kem.kem.length_shared_secret)
	return nil
}
func (kem *KeyEncapsulation) Details() KeyEncapsulationDetails {
	return kem.algDetails
}
func (kem *KeyEncapsulation) GenerateKeyPair() ([]byte, error) {
	publicKey := make([]byte, kem.algDetails.LengthPublicKey)
	kem.secretKey = make([]byte, kem.algDetails.LengthSecretKey)
	rv := C.OQS_KEM_keypair(kem.kem,
		(*C.uint8_t)(unsafe.Pointer(&publicKey[0])),
		(*C.uint8_t)(unsafe.Pointer(&kem.secretKey[0])))
	if rv != C.OQS_SUCCESS {
		return nil, errors.New("can not generate keypair")
	}
	return publicKey, nil
}
func (kem *KeyEncapsulation) ExportSecretKey() []byte {
	return kem.secretKey
}
func (kem *KeyEncapsulation) EncapSecret(publicKey []byte) (ciphertext,
	sharedSecret []byte, err error) {
	if len(publicKey) != kem.algDetails.LengthPublicKey {
		return nil, nil, errors.New("incorrect public key length")
	}
	ciphertext = make([]byte, kem.algDetails.LengthCiphertext)
	sharedSecret = make([]byte, kem.algDetails.LengthSharedSecret)
	rv := C.OQS_KEM_encaps(kem.kem,
		(*C.uint8_t)(unsafe.Pointer(&ciphertext[0])),
		(*C.uint8_t)(unsafe.Pointer(&sharedSecret[0])),
		(*C.uint8_t)(unsafe.Pointer(&publicKey[0])))
	if rv != C.OQS_SUCCESS {
		return nil, nil, errors.New("can not encapsulate secret")
	}
	return ciphertext, sharedSecret, nil
}
func (kem *KeyEncapsulation) DecapSecret(ciphertext []byte) ([]byte, error) {
	if len(ciphertext) != kem.algDetails.LengthCiphertext {
		return nil, errors.New("incorrect ciphertext length")
	}
	if len(kem.secretKey) != kem.algDetails.LengthSecretKey {
		return nil, errors.New("incorrect secret key length, make sure you " +
			"specify one in Init() or run GenerateKeyPair()")
	}
	sharedSecret := make([]byte, kem.algDetails.LengthSharedSecret)
	rv := C.OQS_KEM_decaps(kem.kem,
		(*C.uint8_t)(unsafe.Pointer(&sharedSecret[0])),
		(*C.uchar)(unsafe.Pointer(&ciphertext[0])),
		(*C.uint8_t)(unsafe.Pointer(&kem.secretKey[0])))
	if rv != C.OQS_SUCCESS {
		return nil, errors.New("can not decapsulate secret")
	}
	return sharedSecret, nil
}
func (kem *KeyEncapsulation) Clean() {
	if len(kem.secretKey) > 0 {
		MemCleanse(kem.secretKey)
	}
	C.OQS_KEM_free(kem.kem)
	*kem = KeyEncapsulation{}
}
var enabledSigs []string
var supportedSigs []string
func MaxNumberSigs() int {
	return int(C.OQS_SIG_alg_count())
}
func IsSigEnabled(algName string) bool {
	result := C.OQS_SIG_alg_is_enabled(C.CString(algName))
	return result != 0
}
func IsSigSupported(algName string) bool {
	for i := range supportedSigs {
		if supportedSigs[i] == algName {
			return true
		}
	}
	return false
}
func SigName(algID int) (string, error) {
	if algID >= MaxNumberSigs() {
		return "", errors.New("algorithm ID out of range")
	}
	return C.GoString(C.OQS_SIG_alg_identifier(C.size_t(algID))), nil
}
func SupportedSigs() []string {
	return supportedSigs
}
func EnabledSigs() []string {
	return enabledSigs
}
func init() {
	for i := 0; i < MaxNumberSigs(); i++ {
		sigName, _ := SigName(i)
		supportedSigs = append(supportedSigs, sigName)
		if IsSigEnabled(sigName) {
			enabledSigs = append(enabledSigs, sigName)
		}
	}
}
type SignatureDetails struct {
	ClaimedNISTLevel   int
	IsEUFCMA           bool
	LengthPublicKey    int
	LengthSecretKey    int
	MaxLengthSignature int
	Name               string
	Version            string
}
func (sigDetails SignatureDetails) String() string {
	return fmt.Sprintf("Name: %s\nVersion: %s\nClaimed NIST level: %d\n"+
		"Is EUF_CMA: %v\nLength public key (bytes): %d\nLength secret key ("+
		"bytes): %d\nMaximum length signature (bytes): %d", sigDetails.Name,
		sigDetails.Version, sigDetails.ClaimedNISTLevel, sigDetails.IsEUFCMA,
		sigDetails.LengthPublicKey, sigDetails.LengthSecretKey,
		sigDetails.MaxLengthSignature)
}
type Signature struct {
	sig        *C.OQS_SIG
	secretKey  []byte
	algDetails SignatureDetails
}
func (sig Signature) String() string {
	return fmt.Sprintf("Signature mechanism: %s",
		sig.algDetails.Name)
}
func (sig *Signature) Init(algName string, secretKey []byte) error {
	if !IsSigEnabled(algName) {
		if IsSigSupported(algName) {
			return errors.New(`"` + algName +
				`" signature mechanism is not enabled by OQS`)
		}
		return errors.New(`"` + algName +
			`" signature mechanism is not supported by OQS`)
	}
	sig.sig = C.OQS_SIG_new(C.CString(algName))
	sig.secretKey = secretKey
	sig.algDetails.Name = C.GoString(sig.sig.method_name)
	sig.algDetails.Version = C.GoString(sig.sig.alg_version)
	sig.algDetails.ClaimedNISTLevel = int(sig.sig.claimed_nist_level)
	sig.algDetails.IsEUFCMA = bool(sig.sig.euf_cma)
	sig.algDetails.LengthPublicKey = int(sig.sig.length_public_key)
	sig.algDetails.LengthSecretKey = int(sig.sig.length_secret_key)
	sig.algDetails.MaxLengthSignature = int(sig.sig.length_signature)
	return nil
}
func (sig *Signature) Details() SignatureDetails {
	return sig.algDetails
}
func (sig *Signature) GenerateKeyPair() ([]byte, error) {
	publicKey := make([]byte, sig.algDetails.LengthPublicKey)
	sig.secretKey = make([]byte, sig.algDetails.LengthSecretKey)
	rv := C.OQS_SIG_keypair(sig.sig,
		(*C.uint8_t)(unsafe.Pointer(&publicKey[0])),
		(*C.uint8_t)(unsafe.Pointer(&sig.secretKey[0])))
	if rv != C.OQS_SUCCESS {
		return nil, errors.New("can not generate keypair")
	}
	return publicKey, nil
}
func (sig *Signature) ExportSecretKey() []byte {
	return sig.secretKey
}
func (sig *Signature) Sign(message []byte) ([]byte, error) {
	if len(sig.secretKey) != sig.algDetails.LengthSecretKey {
		return nil, errors.New("incorrect secret key length, make sure you " +
			"specify one in Init() or run GenerateKeyPair()")
	}
	signature := make([]byte, sig.algDetails.MaxLengthSignature)
	var lenSig uint64
	rv := C.OQS_SIG_sign(sig.sig, (*C.uint8_t)(unsafe.Pointer(&signature[0])),
		(*C.size_t)(unsafe.Pointer(&lenSig)),
		(*C.uint8_t)(unsafe.Pointer(&message[0])),
		C.size_t(len(message)), (*C.uint8_t)(unsafe.Pointer(&sig.secretKey[0])))
	if rv != C.OQS_SUCCESS {
		return nil, errors.New("can not sign message")
	}
	return signature[:lenSig], nil
}