JavaScript is required to for searching.
跳过导航链接
退出打印视图
Oracle Solaris 11 开发者安全性指南     Oracle Solaris 11.1 Information Library (简体中文)
为本文档评分
search filter icon
search icon

文档信息

前言

1.  面向开发者的 Oracle Solaris 安全(概述)

2.  开发特权应用程序

3.  编写 PAM 应用程序和服务

4.  编写使用 GSS-API 的应用程序

5.  GSS-API 客户机示例

6.  GSS-API 服务器示例

7.  编写使用 SASL 的应用程序

8.  Oracle Solaris 加密框架介绍

9.  编写用户级加密应用程序

10.  Oracle Solaris 密钥管理框架介绍

Oracle Solaris 密钥管理框架功能

Oracle Solaris 密钥管理框架组件

KMF 密钥管理工具

KMF 策略实施机制

KMF 应用编程接口

Oracle Solaris 密钥管理框架示例应用程序

KMF 头和库

KMF 基本数据类型

KMF 应用程序结果验证

完整的 KMF 应用程序源代码

A.  适用于开发者的安全编码准则

B.  基于 C 的 GSS-API 样例程序

C.  GSS-API 参考信息

D.  指定 OID

E.  SASL 示例的源代码

F.  SASL 参考信息表

词汇表

索引

请告诉我们如何提高我们的文档:
过于简略
不易阅读或难以理解
重要信息缺失
错误的内容
需要翻译的版本
其他
Your rating has been updated
感谢您的反馈!

您的反馈将非常有助于我们提供更好的文档。 您是否愿意参与我们的内容改进并提供进一步的意见?

Oracle Solaris 密钥管理框架示例应用程序

pktool 应用程序是有关如何使用 KMF API 的极佳示例。

本节说明一个使用 KMF 的简单应用程序。本节介绍为执行某些 KMF 操作,应用程序所需执行的基本步骤。此示例假设您有 C 编程方面的经验,并且对公钥技术和标准有基本了解。此示例介绍初始化 KMF 以供使用的步骤,然后创建自签名 X.509v3 证书和关联的 RSA 密钥对。此外,此示例还说明如何使用 KMF 增强的 pktool 命令来验证应用程序是否已成功。

KMF 头和库

要让程序可以访问 KMF 函数原型和类型定义,请包含 kmfapi.h 文件。

#include <stdio.h>
#include <kmfapi.h>

请确保在链接步骤中包含 KMF 库。

$ cc -o kmftest kmftest.c -lkmf

KMF 基本数据类型

有关结果和类型的定义,请参见 kmftypes.h 文件。此示例使用以下 KMF 类型的变量。

KMF_HANDLE_T

KMF 调用的会话句柄

KMF_RETURN

所有 KMF 调用的返回代码

KMF_KEY_HANDLE

KMF 密钥的句柄

KMF_CREDENTIAL

KMF 凭证

KMF_ATTRIBUTE

请确保足够大

KMF_KEYSTORE_TYPE

密钥库类型,如 KMF_KEYSTORE_PK11TOKEN

KMF_KEY_ALG

密钥类型,如 KMF_RSA

KMF_X509_CERTIFICATE

获得签名的数据记录

KMF_X509_NAME

标识名记录

KMF_DATA

最终证书数据记录

KMF_BIGINT

变量长度整数

KMF 应用程序结果验证

通过使用 pktool(1M) 实用程序,用户可以验证程序是否已成功创建证书和密钥对。

$ pktool list objtype=both
Enter pin for Sun Software PKCS#11 softtoken :
Found 1 certificates.
1. (X.509 certificate)
        Label: admin@foobar.com
        ID:
09:ac:7f:1a:01:f7:fc:a9:1a:cd:fd:8f:d4:92:4c:25:bf:b1:97:fe
        Subject: C=US, ST=CA, L=Menlo Park, O=Foobar Inc., OU=Foobar
IT Office, CN=admin@foobar.com
        Issuer: C=US, ST=CA, L=Menlo Park, O=Foobar Inc., OU=Foobar IT
Office, CN=admin@foobar.com
        Serial: 0x452BF693
        X509v3 Subject Alternative Name:
    email:admin@foobar.com

Found 1 keys.
Key #1 - RSA private key: admin@foobar.com

完整的 KMF 应用程序源代码

有关 KMF API 的定义,请参见 libkmf(3LIB) 手册页。

此应用程序执行以下步骤:

  1. 在可以调用任何 KMF 函数之前,应用程序必须首先使用 kmf_initialize() 来初始化 KMF 会话的句柄。此句柄用作大多数 KMF 函数调用的第一个参数。它是一个不透明的数据类型,用于保留该会话的内部状态和上下文信息。

  2. 此示例应用程序使用 PKCS#11 密钥库。使用 kmf_configure_keystore() 来定义将来操作要使用的令牌。

  3. 创建证书或 PKCS#10 CSR 的第一步是生成密钥对。使用 kmf_create_keypair() 来创建所需的公钥和私钥,并将私钥存储在指定密钥库中。该函数会将句柄返回到应用程序,以便调用者可以在将来的操作中引用公钥和私钥对象(如有必要)。

  4. 建立密钥对后,使用 kmf_set_cert_pubkey()kmf_set_cert_version() 来填充用于生成最终证书的模板记录。KMF 可提供不同的 API 来设置 X.509v3 证书的各种字段(包括扩展)。使用 kmf_hexstr_to_bytes()kmf_set_cert_serial()kmf_set_cert_validity()kmf_set_cert_sig_alg() 来设置序列号。该序列号是 KMF_BIGINT 记录。使用 kmf_dn_parser()kmf_set_cert_subject()kmf_set_cert_issuer() 来创建 KMF_X509_NAME 结构。

  5. 由于这是自签名证书创建练习,所以该应用程序使用随证书自身的公钥提供的私钥对上面创建的证书模板进行签名。该 kmf_sign_cert() 操作将导致生成 KMF_DATA 记录,该记录包含 ASN.1 编码的 X.509v3 证书数据。

  6. 现在,已对证书进行签名并且为其最终格式,可以将其存储在任何密钥库中。使用 kmf_store_cert() 将证书存储在该应用程序开始时定义的 PKCS#11 令牌中。此时,也可以将证书存储在 NSS 或 OpenSSL 文件中。

  7. 不再需要 KMF 生成的数据结构时,应清除分配给该数据结构的内存。KMF 提供了便于使用的 API,以便正确地解除与这些对象关联的内存的分配。为了节省资源,强烈建议正确地清除内存。清除接口包括 kmf_free_data()kmf_free_dn()kmf_finalize()

下面是此示例应用程序的完整源代码,包括所有数据类型和辅助 (helper) 函数。编译时,请确保包含 KMF 库。

/*
 * KMF Example code for generating a self-signed X.509 certificate.
 * This is completely unsupported and is just to be used as an example.
 *
 * Compile:
 * $ cc -o keytest keytest.c -lkmf
 *
 * Run:
 * $  ./keytest
 *
 * Once complete, the results can be verified using the pktool(1) command:
 *
 * $ pktool list 
 * This should show an RSA public key labeled "keytest" and a cert labeled "keytest".
 *
 * The objects created by this program can be deleted from the keystore
 * using pktool(1) also:
 *
 * $ pktool delete label=keytest
 *
 */ 
#include <stdio.h>
#include <strings.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <tzfile.h>

#include <kmfapi.h>

int
main(int argc, char *argv[])
{
    KMF_HANDLE_T         kmfhandle;
    KMF_RETURN           ret;
    char                 opt, *str = NULL;
    extern char          *optarg;
    KMF_KEY_HANDLE       prikey, pubkey;
    KMF_CREDENTIAL       cred;
    KMF_ATTRIBUTE        attrlist[16]; /* this needs to be big enough */
    KMF_KEYSTORE_TYPE    kstype;
    KMF_KEY_ALG          keytype;
    KMF_KEY_HANDLE       prik, pubk;
    KMF_X509_CERTIFICATE certstruct;
    KMF_X509_NAME        certsubject, certissuer;
    KMF_DATA             rawcert;
    KMF_BIGINT           serno;
    char                 *token = "Sun Software PKCS#11 softtoken";
    char                 *keylabel = "keytest";
    boolean_t            readonly = B_FALSE;
    uint32_t             keylen = 1024;
    uint32_t             ltime = SECSPERDAY * DAYSPERNYEAR; /* seconds in a
                             year (see tzfile.h) */
    char                 prompt[1024];
    int                  numattrs;

    (void) memset(&certstruct, 0, sizeof (certstruct));
    (void) memset(&rawcert, 0, sizeof (rawcert));
    (void) memset(&certissuer, 0, sizeof (certissuer));
    (void) memset(&certsubject, 0, sizeof (certsubject));

    /*
     * Initialize a KMF handle for use in future calls.
     */
    ret = kmf_initialize(&kmfhandle, NULL, NULL);
    if (ret != KMF_OK) {
        printf("kmf_initialize failed: 0x%0x\n", ret);
        exit(1);
    }

    /* We want to use the PKCS11 keystore */
    kstype = KMF_KEYSTORE_PK11TOKEN;
    numattrs = 0;
    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYSTORE_TYPE_ATTR,
        &kstype, sizeof (kstype));
    numattrs++;

    /* Indicate which PKCS11 token will be used */
    kmf_set_attr_at_index(attrlist, numattrs, KMF_TOKEN_LABEL_ATTR,
        token, strlen(token));
    numattrs++;

    kmf_set_attr_at_index(attrlist, numattrs, KMF_READONLY_ATTR,
        &readonly, sizeof (readonly));
    numattrs++;

    ret = kmf_configure_keystore(kmfhandle, numattrs, attrlist);
    if (ret != KMF_OK)
        exit (ret);

    /* Reset the attribute count for a new command */
    numattrs = 0;

    /*
     * Get the PIN to access the token.
     */
    (void) snprintf(prompt, sizeof (prompt), "Enter PIN for %s:", token);
    cred.cred = getpassphrase(prompt);
    if (cred.cred != NULL) {
        cred.credlen = strlen(cred.cred);
        kmf_set_attr_at_index(attrlist, numattrs, KMF_CREDENTIAL_ATTR,
            &cred, sizeof (cred));
        numattrs++;
    }

    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYSTORE_TYPE_ATTR,
        &kstype, sizeof (kstype));
    numattrs++;

    keytype = KMF_RSA;
    keylen = 1024;
    keylabel = "keytest";

    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYALG_ATTR,
        &keytype, sizeof (keytype));
    numattrs++;

    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYLENGTH_ATTR,
        &keylen, sizeof (keylen));
    numattrs++;

    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYLABEL_ATTR,
        keylabel, strlen(keylabel));
    numattrs++;

    kmf_set_attr_at_index(attrlist, numattrs, KMF_CREDENTIAL_ATTR,
        &cred, sizeof (cred));
    numattrs++;

    /*
     * Set the handles so they can be used later.
     */
    kmf_set_attr_at_index(attrlist, numattrs, KMF_PRIVKEY_HANDLE_ATTR,
        &prik, sizeof (prik));
    numattrs++;

    kmf_set_attr_at_index(attrlist, numattrs, KMF_PUBKEY_HANDLE_ATTR,
        &pubk, sizeof (pubk));
    numattrs++;

    ret = kmf_create_keypair(kmfhandle, numattrs, attrlist);
    if (ret != KMF_OK) {
        printf("kmf_create_keypair error: 0x%02x\n", ret);
        goto cleanup;
    }

    /*
     * Now the keys have been created, generate an X.509 certificate
     * by populating the template and signing it.
     */
    if ((ret = kmf_set_cert_pubkey(kmfhandle, &pubk, &certstruct))) {
        printf("kmf_set_cert_pubkey error: 0x%02x\n", ret);
        goto cleanup;
    }

    /* Version "2" is for an x509.v3 certificate */
    if ((ret = kmf_set_cert_version(&certstruct, 2))) {
        printf("kmf_set_cert_version error: 0x%02x\n", ret);
        goto cleanup;
    }

    /*
     * Set up the serial number, it must be a KMF_BIGINT record.
     */
    if ((ret = kmf_hexstr_to_bytes((uchar_t *)"0x010203", &serno.val, \
            &serno.len))) {
        printf("kmf_hexstr_to_bytes error: 0x%02x\n", ret);
        goto cleanup;
    }

    if ((ret = kmf_set_cert_serial(&certstruct, &serno))) {
        printf("kmf_set_cert_serial error: 0x%02x\n", ret);
        goto cleanup;
    }

    if ((ret = kmf_set_cert_validity(&certstruct, NULL, ltime))) {
        printf("kmf_set_cert_validity error: 0x%02x\n", ret);
        goto cleanup;
    }

    if ((ret = kmf_set_cert_sig_alg(&certstruct, KMF_ALGID_SHA1WithRSA))) {
        printf("kmf_set_cert_sig_alg error: 0x%02x\n", ret);
        goto cleanup;
    }

    /*
     * Create a KMF_X509_NAME struct by parsing a distinguished name.
     */
    if ((ret = kmf_dn_parser("cn=testcert", &certsubject))) {
        printf("kmf_dn_parser error: 0x%02x\n", ret);
        goto cleanup;
    }

    if ((ret = kmf_dn_parser("cn=testcert", &certissuer))) {
        printf("kmf_dn_parser error: 0x%02x\n", ret);
        goto cleanup;
    }

    if ((ret = kmf_set_cert_subject(&certstruct, &certsubject))) {
        printf("kmf_set_cert_sig_alg error: 0x%02x\n", ret);
        goto cleanup;
    }

    if ((ret = kmf_set_cert_issuer(&certstruct, &certissuer))) {
        printf("kmf_set_cert_sig_alg error: 0x%02x\n", ret);
        goto cleanup;
    }

    /*
     * Now we have the certstruct setup with the minimal amount needed
     * to generate a self-signed cert.  Put together the attributes to 
     * call kmf_sign_cert.
     */
    numattrs = 0;
    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYSTORE_TYPE_ATTR,
            &kstype, sizeof (kstype));
    numattrs++;

    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEY_HANDLE_ATTR,
            &prik, sizeof (KMF_KEY_HANDLE_ATTR));
    numattrs++;

    /* The X509 template structure to be signed goes here. */
    kmf_set_attr_at_index(attrlist, numattrs, KMF_X509_CERTIFICATE_ATTR,
            &certstruct, sizeof (KMF_X509_CERTIFICATE));
    numattrs++;

    /*
     * Set the output buffer for the signed cert.
     * This will be a block of raw ASN.1 data.
     */
    kmf_set_attr_at_index(attrlist, numattrs, KMF_CERT_DATA_ATTR,
            &rawcert, sizeof (KMF_DATA));
    numattrs++;

    if ((ret = kmf_sign_cert(kmfhandle, numattrs, attrlist))) {
        printf("kmf_sign_cert error: 0x%02x\n", ret);
        goto cleanup;
    }

    /*
     * Now we have the certificate and we want to store it in the
     * keystore (which is the PKCS11 token in this example).
     */
    numattrs = 0;
    kmf_set_attr_at_index(attrlist, numattrs, KMF_KEYSTORE_TYPE_ATTR,
            &kstype, sizeof (kstype));
    numattrs++;
    kmf_set_attr_at_index(attrlist, numattrs, KMF_CERT_DATA_ATTR,
            &rawcert, sizeof (KMF_DATA));
    numattrs++;

    /* Use the same label as the public key */
    kmf_set_attr_at_index(attrlist, numattrs, KMF_CERT_LABEL_ATTR,
        keylabel, strlen(keylabel));
    numattrs++;

    if ((ret = kmf_store_cert(kmfhandle, numattrs, attrlist))) {
        printf("kmf_store_cert error: 0x%02x\n", ret);
                goto cleanup;
    }

cleanup:
    kmf_free_data(&rawcert);
    kmf_free_dn(&certissuer);
    kmf_free_dn(&certsubject);
    kmf_finalize(kmfhandle);

    return (ret);
}