yebin-yu / openssh_with_ukey

Other
0 stars 0 forks source link

UKEY 进展 #12

Closed yebin-yu closed 6 months ago

yebin-yu commented 6 months ago

2024-04-19 已经能够通过公钥测试,并在客户端成功对签名信息做哈希,并签名,然后发送。现在问题在服务端接受到签名信息后表示不允许这个公钥。

客户端准备

客户端的公钥硬编码在代码中,使用我的ukey就不需要修改 ukey的初始密码是12345678 代码仓为:20240408_yuyebin_userauth_with_ukey

//base64.b64encode(bytes.fromhex("00000003736d3200000003736d3200000041" + "04" +
            //                         'a3787ede1d0bc4e1c3089c9ae2137cb123b7594e4ae2dd859b890e1ff9546521' +
            //                         '981e2c635fb7295728aa05bccb18c409b71bf52eec226abc9152153f838fcbce'))
            unsigned char *buffer = "sm2 AAAAA3NtMgAAAANzbTIAAABBBKN4ft4dC8ThwwicmuITfLEjt1lOSuLdhZuJDh/5VGUhmB4sY1+3KVcoqgW8yxjECbcb9S7sImq8kVIVP4OPy84= root@yebinyu";
**修改 /root/.ssh/config **
root@yebinyu:/home/openssh_with_ukey# cat /root/.ssh/config 
Host *
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  IdentityFile ~/.ssh/id_sm2        # 这里把默认的私钥地址改成/root/.ssh/id_sm2,不需要创建文件,没有这个文件就行。
  IdentitiesOnly yes
  HashKnownHosts no
root@yebinyu:/home/openssh_with_ukey# 

新增配置(直接放在/etc/ssh/ssh_config中也行)

root@yebinyu:/home/openssh_with_ukey# cat /etc/ssh/ssh_config.d/sm2.conf 
PubkeyAcceptedAlgorithms sm2

公钥

服务端准备

修改配置文件

root@yebinyu:/home/openssh_with_ukey# cat /etc/ssh/sshd_config_sm2 | grep -v "#" | grep -v "^$"
HostKey /root/.ssh/id_sm2
PermitRootLogin yes
PubkeyAuthentication yes
AuthorizedKeysFile      /authorized_keys
X11Forwarding yes
Subsystem       sftp    /usr/lib/ssh/sftp-server
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL
MACs hmac-sm3,umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
HostKeyAlgorithms sm2,rsa-sha2-512,rsa-sha2-256,ssh-rsa,ecdsa-sha2-nistp256,ssh-ed25519
KexAlgorithms  sm2-sm3,curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256
Ciphers sm4-ctr,chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
PubkeyAcceptedKeyTypes sm2
FingerprintHash sm3
PubkeyAcceptedAlgorithms sm2
PasswordAuthentication no
AllowUsers *
LOGLEVEL DEBUG3
root@yebinyu:/home/openssh_with_ukey# 

修改保存公钥的文件,地址在上面的config中AuthorizedKeysFile /authorized_keys

sm2 AAAA3NtMgAAAANzbTIAAABBBKN4ft4dC8ThwwicmuITfLEjt1lOSuLdhZuJDh/5VGUhmB4sY1+3KVcoqgW8yxjECbcb9S7sImq8kVIVP4OPy84= root@yebinyu

现状

sshd在这里报错:

image
yebin-yu commented 6 months ago

当前签名代码


void SM2_gmSig2OpensslSig(ECCSIGNATUREBLOB *sigBlob, unsigned char **sig, size_t *len)
{
    BIGNUM *rB=NULL;
    BIGNUM *sB=NULL;

    BYTE *r = sigBlob->r+32;
    BYTE *s = sigBlob->s+32;

    rB = BN_bin2bn(r, 32, NULL);
    if(rB == NULL) {return NULL;}
    sB = BN_bin2bn(s, 32, NULL);
    if(sB == NULL) {return NULL;}

    ECDSA_SIG *ecdsaSig = ECDSA_SIG_new();
    if (ecdsaSig == NULL) {return NULL;}

    if(ECDSA_SIG_set0(ecdsaSig, rB, sB) != 1) {
        return NULL;
    }

    unsigned char* sig_temp = NULL;
    int sigLen = i2d_ECDSA_SIG(ecdsaSig, sig);
    // *sig = sig_temp;
    printf("%s", *sig);
    *len = sigLen;
}

int EVP_Digest(const void *data, size_t count,
               unsigned char *md, unsigned int *size, const EVP_MD *type,
               ENGINE *impl, struct sshkey *sign_key)
{

    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
    int ret;
    EVP_PKEY *key_sm2 = NULL;

    if ((key_sm2 = EVP_PKEY_new()) == NULL) {
        return SSH_ERR_ALLOC_FAIL;
    }

    if ((EVP_PKEY_set1_EC_KEY(key_sm2, sign_key->ecdsa)) != 1) {
        ret = SSH_ERR_INTERNAL_ERROR;
        return 0;
    }

    if (ctx == NULL)
        return 0;
    EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT);
    ret = EVP_DigestInit_ex(ctx, type, impl)
        && EVP_DigestUpdate(ctx, data, count)
        && EVP_DigestFinal_ex(ctx, md, size);
    EVP_MD_CTX_free(ctx);

    return ret;
}

static int
init_ukey_container(HCONTAINER *hcontainer)
{
    HANDLE hdev = NULL;
    ULONG ulRslt = SAR_OK;

    // 枚举获取设备名,这里的逻辑应该是自动获取然后赋值
    // ukey上获取到的值应该为:3DC2105010CFD4C62A42E5375DA38B9
    char szDevName[256] = {0}; 
    ULONG ulDevNameLen = 256;
    ulRslt = SKF_EnumDev(TRUE, szDevName, &ulDevNameLen);
    printf("szDevName: %s \n", szDevName);
    if (ulRslt != SAR_OK) {
        debug("SKF_EnumDev ERROR \n");
        return 1;
    }

    // 连接设备
    ulRslt = SKF_ConnectDev(szDevName, &hdev);
    if (ulRslt != SAR_OK) {
        debug("SKF_ConnectDev ERROR \n");
        return 1;
    }

    // 获取application,这里的逻辑应该是自动获取然后赋值
    // ukey上获取到的值应该为:GM3000RSA
    char appName[256] = {0}; 
    ULONG appnameLen = 256;
    ulRslt = SKF_EnumApplication(hdev, appName, &appnameLen);
    printf("appName: %s\n", appName);
    if (ulRslt != SAR_OK) {
        debug("SKF_EnumApplication ERROR \n");
        return 1;
    }

    // 打开应用
    HANDLE happ;
    ulRslt = SKF_OpenApplication(hdev, appName, &happ);
    if (ulRslt != SAR_OK) {
        debug("SKF_OpenApplication ERROR \n");
        return 1;
    }

    // 验证pin码
    char pinStr[32];
    ULONG retryCntMax = 3;
    ULONG currentRetryCnt = 0;
    printf("UKEY pin:");
    scanf("%s", pinStr);
    ulRslt = SKF_VerifyPIN(happ, USER_TYPE, pinStr, &retryCntMax);
    while (ulRslt != SAR_OK && currentRetryCnt++ < retryCntMax) {
        sleep(2);  // 防止暴力破解,等待两秒
        printf("UKEY pin again:");
        scanf("%s", pinStr);
        ulRslt = SKF_VerifyPIN(happ, USER_TYPE, pinStr, &retryCntMax);
    }
    if (ulRslt != SAR_OK) {
        debug("SKF_VerifyPIN ERROR \n");
        return 1;
    }

    // 获取容器名
    // ukey上获取到的值应该为:sm2
    char containerName[256] = {0};
    ULONG containerNameLen = 256;
    ulRslt = SKF_EnumContainer(happ, containerName, &containerNameLen);
    printf("containerName: %s\n", containerName);
    if (ulRslt != SAR_OK) {
        debug("SKF_EnumContainer ERROR \n");
        return 1;
    }

    // 打开容器
    ulRslt = SKF_OpenContainer(happ, containerName, hcontainer);
    if (ulRslt != SAR_OK) {
        debug("SKF_OpenContainer ERROR \n");
        return 1;
    }

    return SAR_OK;
}

static int
ukey_get_sig(const u_char *data, size_t datalen, u_char **sig, size_t *slen, struct sshkey *sign_key)
{   
    // get container handle
    ULONG ulRslt = SAR_OK;
    HCONTAINER container = NULL;
    if (init_ukey_container(&container) != 0) {
        debug("init_ukey_container ERROR \n");
        return 1;
    }

    // hash
    unsigned char hashRslt[32] = {0};
    int hashLen;
    if(1 != EVP_Digest(data, datalen, hashRslt, &hashLen, EVP_sm3(), NULL, sign_key)) {
        debug("EVP_Digest ERROR \n");
        return 1;
    }

    // sign
    ECCSIGNATUREBLOB stSign = {0};
    ulRslt = SKF_ECCSignData(container, hashRslt, hashLen, &stSign);
    if (ulRslt != SAR_OK) {
        debug("SKF_ECCSignData ERROR \n");
        return 1;
    }

    SM2_gmSig2OpensslSig(&stSign, sig, slen);
    return 0;
}
yebin-yu commented 6 months ago

hash的部分用ukey的代码代替

    // hash
    unsigned char hashRslt[32] = {0};
    int hashLen;

    ECCPUBLICKEYBLOB *blob = (ECCPUBLICKEYBLOB *)buf;
    const unsigned char *sm2_id = (const unsigned char *)"1234567812345678";
    HANDLE phHash = NULL;
    SKF_DigestInit(hDev, SGD_SM3, blob, sm2_id, 16, &phHash);
    SKF_Digest(phHash, data, datalen, hashRslt, &hashLen);

    // if(1 != EVP_Digest(data, datalen, hashRslt, &hashLen, EVP_sm3(), NULL, sign_key)) {
    //  debug("EVP_Digest ERROR \n");
    //  return 1;
    // }
yebin-yu commented 6 months ago

最新的代码

static int
ukey_get_sig(u_char *data, size_t datalen, u_char **sig, size_t *slen, struct sshkey *sign_key)
{   
    // get container handle
    ULONG ulRslt = SAR_OK;
    HCONTAINER container = NULL;
    DEVHANDLE hDev = NULL;
    if (init_ukey_container(&container, &hDev) != 0) {
        debug("init_ukey_container ERROR \n");
        return 1;
    }

    BYTE buf[132] = {0};
    ULONG bufLen = sizeof(buf);
    ulRslt = SKF_ExportPublicKey(container, TRUE, buf, &bufLen);
    if (ulRslt != SAR_OK) {
        debug("SKF_ExportPublicKey ERROR \n");
        return 1;
    }

    // hash
    unsigned char hashRslt[32] = {0};
    int hashLen;

    ECCPUBLICKEYBLOB *blob = (ECCPUBLICKEYBLOB *)buf;
    const unsigned char *sm2_id = (const unsigned char *)"1234567812345678";
    HANDLE phHash = NULL;
    ulRslt = SKF_DigestInit(hDev, SGD_SM3, blob, sm2_id, 16, &phHash);
    if (ulRslt != SAR_OK) {
        debug("ulRsltSKF_DigestInit:%d", ulRslt);
    }
    ulRslt = SKF_Digest(phHash, data, datalen, hashRslt, &hashLen);
    if (ulRslt != SAR_OK) {
        debug("SKF_Digest:%d", ulRslt);
    }

    // if(1 != EVP_Digest(data, datalen, hashRslt, &hashLen, EVP_sm3(), NULL, sign_key)) {
    //  debug("EVP_Digest ERROR \n");
    //  return 1;
    // }

    // sign
    ECCSIGNATUREBLOB stSign = {0};
    ulRslt = SKF_ECCSignData(container, hashRslt, hashLen, &stSign);
    if (ulRslt != SAR_OK) {
        debug("SKF_ECCSignData ERROR \n");
        return 1;
    }

    SM2_gmSig2OpensslSig(&stSign, sig, slen);
    return 0;
}
yebin-yu commented 6 months ago

使用update和final


static int
ukey_get_sig(u_char *data, size_t datalen, u_char **sig, size_t *slen, struct sshkey *sign_key)
{   
    // get container handle
    ULONG ulRslt = SAR_OK;
    HCONTAINER container = NULL;
    DEVHANDLE hDev = NULL;
    if (init_ukey_container(&container, &hDev) != 0) {
        debug("init_ukey_container ERROR \n");
        return 1;
    }

    BYTE buf[132] = {0};
    ULONG bufLen = sizeof(buf);
    ulRslt = SKF_ExportPublicKey(container, TRUE, buf, &bufLen);
    if (ulRslt != SAR_OK) {
        debug("SKF_ExportPublicKey ERROR \n");
        return 1;
    }

    // hash
    unsigned char hashRslt[32] = {0};
    int hashLen;

    ECCPUBLICKEYBLOB *blob = (ECCPUBLICKEYBLOB *)buf;
    const unsigned char *sm2_id = (const unsigned char *)"1234567812345678";
    HANDLE phHash = NULL;
    ulRslt = SKF_DigestInit(hDev, SGD_SM3, blob, sm2_id, 16, &phHash);
    if (ulRslt != SAR_OK) {
        debug("ulRsltSKF_DigestInit:%d", ulRslt);
    }
    ulRslt = SKF_DigestUpdate(phHash, data, datalen);
    if (ulRslt != SAR_OK) {
        debug("SKF_Digest:%d", ulRslt);
    }
    ulRslt = SKF_DigestFinal(phHash, hashRslt, &hashLen);
    if (ulRslt != SAR_OK) {
        debug("SKF_DigestFinal:%d", ulRslt);
    }

    // hash with EVP_Digest(openssl)
    // if(1 != EVP_Digest(data, datalen, hashRslt, &hashLen, EVP_sm3(), NULL, sign_key)) {
    //  debug("EVP_Digest ERROR \n");
    //  return 1;
    // }

    // sign
    ECCSIGNATUREBLOB stSign = {0};
    ulRslt = SKF_ECCSignData(container, hashRslt, hashLen, &stSign);
    if (ulRslt != SAR_OK) {
        debug("SKF_ECCSignData ERROR \n");
        return 1;
    }

    SM2_gmSig2OpensslSig(&stSign, sig, slen);
    return 0;
}
yebin-yu commented 6 months ago

最新的:

static int
ukey_get_sig(u_char *data, size_t datalen, u_char **sig, size_t *slen, struct sshkey *sign_key)
{   
    // get container handle
    ULONG ulRslt = SAR_OK;
    HCONTAINER container = NULL;
    DEVHANDLE hDev = NULL;
    if (init_ukey_container(&container, &hDev) != 0) {
        debug("init_ukey_container ERROR \n");
        return 1;
    }

    BYTE buf[132] = {0};
    ULONG bufLen = sizeof(buf);
    ulRslt = SKF_ExportPublicKey(container, TRUE, buf, &bufLen);
    if (ulRslt != SAR_OK) {
        debug("SKF_ExportPublicKey ERROR \n");
        return 1;
    }

    // hash
    unsigned char hashRslt[32] = {0};
    int hashLen = 32;
    // unsigned char *hashRslt = NULL;

    ECCPUBLICKEYBLOB *blob = (ECCPUBLICKEYBLOB *)buf;
    const unsigned char *sm2_id = (const unsigned char *)"1234567812345678";
    HANDLE phHash = NULL;
    ulRslt = SKF_DigestInit(hDev, SGD_SM3, sm2_id, 16, 0, &phHash);
    if (ulRslt != SAR_OK) {
        debug("ulRsltSKF_DigestInit:%d", ulRslt);
    }

    ulRslt = SKF_Digest(phHash, data, 256, hashRslt, &hashLen);
    if (ulRslt != SAR_OK) {
        debug("SKF_Digest:%d", ulRslt);
    }

    // sign
    ECCSIGNATUREBLOB stSign = {0};
    ulRslt = SKF_ECCSignData(container, hashRslt, hashLen, &stSign);
    if (ulRslt != SAR_OK) {
        debug("SKF_ECCSignData ERROR \n");
        return 1;
    }

    SM2_gmSig2OpensslSig(&stSign, sig, slen);
    return 0;
}