mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-06-29 18:38:36 +08:00
cLib: First implementation of gj_generate_ssh_keys
We're using openssl to do so. This was quite confusing. This really helped https://stackoverflow.com/a/12750816/147435
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
CC=clang
|
CC=clang
|
||||||
|
|
||||||
test: gitjournal.c test.c keygen.c
|
test: gitjournal.c test.c keygen.c
|
||||||
$(CC) -o test -g test.c gitjournal.c keygen.c -lgit2
|
$(CC) -o test -g test.c gitjournal.c keygen.c -lgit2 -lssl -lcrypto
|
||||||
|
@ -4,90 +4,158 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
/*
|
#include <memory.h>
|
||||||
#include <libssh/libssh.h>
|
|
||||||
#include <libssh/callbacks.h>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define UNUSED(x) (void)(x)
|
#include <openssl/bio.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
|
||||||
void change_pubickey_comment(const char *filename, const char *comment)
|
static unsigned char pSshHeader[11] = {0x00, 0x00, 0x00, 0x07, 0x73, 0x73, 0x68, 0x2D, 0x72, 0x73, 0x61};
|
||||||
|
|
||||||
|
static int SshEncodeBuffer(unsigned char *pEncoding, int bufferLen, unsigned char *pBuffer)
|
||||||
{
|
{
|
||||||
FILE *fp = fopen(filename, "r");
|
int adjustedLen = bufferLen, index;
|
||||||
char buff[10000];
|
if (*pBuffer & 0x80)
|
||||||
fgets(buff, 10000, fp);
|
{
|
||||||
fclose(fp);
|
adjustedLen++;
|
||||||
|
pEncoding[4] = 0;
|
||||||
// Remove the comment
|
index = 5;
|
||||||
char *end = strchr(strchr(buff, ' ') + 1, ' ');
|
}
|
||||||
int len = end - buff + 1;
|
else
|
||||||
buff[len] = 0;
|
{
|
||||||
|
index = 4;
|
||||||
// Add custom comment
|
}
|
||||||
strcat(buff, comment);
|
pEncoding[0] = (unsigned char)(adjustedLen >> 24);
|
||||||
strcat(buff, "\n");
|
pEncoding[1] = (unsigned char)(adjustedLen >> 16);
|
||||||
|
pEncoding[2] = (unsigned char)(adjustedLen >> 8);
|
||||||
// Write the file back
|
pEncoding[3] = (unsigned char)(adjustedLen);
|
||||||
fp = fopen(filename, "w");
|
memcpy(&pEncoding[index], pBuffer, bufferLen);
|
||||||
fputs(buff, fp);
|
return index + bufferLen;
|
||||||
fclose(fp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gj_ssh_log_callback(int priority, const char *function, const char *buffer, void *userdata)
|
int write_rsa_public_key(RSA *pRsa, const char *file_path, const char *comment)
|
||||||
{
|
{
|
||||||
UNUSED(userdata);
|
int iRet = 0;
|
||||||
char log_str[1024];
|
int encodingLength = 0;
|
||||||
sprintf(log_str, "LIB_SSH P%d : %s : %s\n", priority, function, buffer);
|
int index = 0;
|
||||||
gj_log(log_str);
|
unsigned char *nBytes = NULL, *eBytes = NULL;
|
||||||
|
unsigned char *pEncoding = NULL;
|
||||||
|
FILE *pFile = NULL;
|
||||||
|
BIO *bio, *b64;
|
||||||
|
|
||||||
|
ERR_load_crypto_strings();
|
||||||
|
OpenSSL_add_all_algorithms();
|
||||||
|
|
||||||
|
const BIGNUM *pRsa_mod = NULL;
|
||||||
|
const BIGNUM *pRsa_exp = NULL;
|
||||||
|
|
||||||
|
RSA_get0_key(pRsa, &pRsa_mod, &pRsa_exp, NULL);
|
||||||
|
|
||||||
|
// reading the modulus
|
||||||
|
int nLen = BN_num_bytes(pRsa_mod);
|
||||||
|
nBytes = (unsigned char *)malloc(nLen);
|
||||||
|
BN_bn2bin(pRsa_mod, nBytes);
|
||||||
|
|
||||||
|
// reading the public exponent
|
||||||
|
int eLen = BN_num_bytes(pRsa_exp);
|
||||||
|
eBytes = (unsigned char *)malloc(eLen);
|
||||||
|
BN_bn2bin(pRsa_exp, eBytes);
|
||||||
|
|
||||||
|
printf("nLen: %d\n", nLen);
|
||||||
|
printf("nLen2: %d\n", BN_num_bytes(pRsa_mod));
|
||||||
|
printf("eLen: %d\n", eLen);
|
||||||
|
|
||||||
|
encodingLength = 11 + 4 + eLen + 4 + nLen;
|
||||||
|
// correct depending on the MSB of e and N
|
||||||
|
if (eBytes[0] & 0x80)
|
||||||
|
encodingLength++;
|
||||||
|
if (nBytes[0] & 0x80)
|
||||||
|
encodingLength++;
|
||||||
|
|
||||||
|
pEncoding = (unsigned char *)malloc(encodingLength);
|
||||||
|
memset(pEncoding, 0, encodingLength);
|
||||||
|
memcpy(pEncoding, pSshHeader, 11);
|
||||||
|
|
||||||
|
index = SshEncodeBuffer(&pEncoding[11], eLen, eBytes);
|
||||||
|
index = SshEncodeBuffer(&pEncoding[11 + index], nLen, nBytes);
|
||||||
|
|
||||||
|
b64 = BIO_new(BIO_f_base64());
|
||||||
|
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
||||||
|
|
||||||
|
pFile = fopen(file_path, "w");
|
||||||
|
bio = BIO_new_fp(pFile, BIO_CLOSE);
|
||||||
|
BIO_printf(bio, "ssh-rsa ");
|
||||||
|
bio = BIO_push(b64, bio);
|
||||||
|
BIO_write(bio, pEncoding, encodingLength);
|
||||||
|
BIO_flush(bio);
|
||||||
|
bio = BIO_pop(b64);
|
||||||
|
BIO_printf(bio, " %s\n", comment);
|
||||||
|
BIO_flush(bio);
|
||||||
|
BIO_free_all(bio);
|
||||||
|
BIO_free(b64);
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (pFile)
|
||||||
|
fclose(pFile);
|
||||||
|
|
||||||
|
free(nBytes);
|
||||||
|
free(eBytes);
|
||||||
|
free(pEncoding);
|
||||||
|
|
||||||
|
EVP_cleanup();
|
||||||
|
ERR_free_strings();
|
||||||
|
return iRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gj_generate_ssh_keys(const char *private_key_path,
|
int gj_generate_ssh_keys(const char *private_key_path,
|
||||||
const char *public_key_path, const char *comment)
|
const char *public_key_path, const char *comment)
|
||||||
{
|
{
|
||||||
UNUSED(private_key_path);
|
int ret = 0;
|
||||||
UNUSED(public_key_path);
|
RSA *rsa = NULL;
|
||||||
UNUSED(comment);
|
|
||||||
|
|
||||||
return 1;
|
BIGNUM *bne = NULL;
|
||||||
/*
|
BIO *bp_private = NULL;
|
||||||
ssh_key key;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
ssh_set_log_level(SSH_LOG_FUNCTIONS);
|
int bits = 1024 * 4;
|
||||||
ssh_set_log_callback(gj_ssh_log_callback);
|
unsigned long e = RSA_F4;
|
||||||
|
|
||||||
err = ssh_pki_generate(SSH_KEYTYPE_RSA, 4096, &key);
|
// Generate rsa key
|
||||||
if (err != SSH_OK)
|
bne = BN_new();
|
||||||
|
ret = BN_set_word(bne, e);
|
||||||
|
if (ret != 1)
|
||||||
{
|
{
|
||||||
gj_log("LIBSSH: ssh_pki_generate failed\n");
|
goto cleanup;
|
||||||
//printf("Error: %s", ssh_get_error());
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *password = "";
|
rsa = RSA_new();
|
||||||
err = ssh_pki_export_privkey_file(key, password, NULL, NULL, private_key_path);
|
ret = RSA_generate_key_ex(rsa, bits, bne, NULL);
|
||||||
if (err != SSH_OK)
|
if (ret != 1)
|
||||||
{
|
{
|
||||||
gj_log("LIBSSH: ssh_pki_export_privkey_file failed\n");
|
goto cleanup;
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ssh_pki_export_pubkey_file(key, public_key_path);
|
// Save private key
|
||||||
if (err != SSH_OK)
|
bp_private = BIO_new_file(private_key_path, "w+");
|
||||||
|
ret = PEM_write_bio_RSAPrivateKey(bp_private, rsa, NULL, NULL, 0, NULL, NULL);
|
||||||
|
if (ret != 1)
|
||||||
{
|
{
|
||||||
gj_log("LIBSSH: ssh_pki_export_pubkey_file failed\n");
|
|
||||||
return err;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_key_free(key);
|
// Save public key
|
||||||
|
ret = write_rsa_public_key(rsa, public_key_path, comment);
|
||||||
change_pubickey_comment(public_key_path, comment);
|
if (ret != 1)
|
||||||
|
{
|
||||||
// Change file permissions
|
goto cleanup;
|
||||||
char mode[] = "0600";
|
}
|
||||||
int modeInt = strtol(mode, 0, 8);
|
|
||||||
chmod(private_key_path, modeInt);
|
cleanup:
|
||||||
|
BIO_free_all(bp_private);
|
||||||
return 0;
|
RSA_free(rsa);
|
||||||
*/
|
BN_free(bne);
|
||||||
|
|
||||||
|
return (ret == 1);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user