diff options
author | Nick Mathewson <nickm@torproject.org> | 2004-03-30 19:47:32 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2004-03-30 19:47:32 +0000 |
commit | 6ea95488d2e2b519a33bd7c2f391b520a6dc6b97 (patch) | |
tree | 006e392500cc8439c4db421a6b29e0a002e860f9 /src | |
parent | abcf3d934186d02e54253a57504138b900521ef7 (diff) | |
download | tor-6ea95488d2e2b519a33bd7c2f391b520a6dc6b97.tar tor-6ea95488d2e2b519a33bd7c2f391b520a6dc6b97.tar.gz |
Add more key manipulation functions, and base32 functions, to crypto
svn:r1395
Diffstat (limited to 'src')
-rw-r--r-- | src/common/crypto.c | 83 | ||||
-rw-r--r-- | src/common/crypto.h | 6 | ||||
-rw-r--r-- | src/or/test.c | 17 |
3 files changed, 96 insertions, 10 deletions
diff --git a/src/common/crypto.c b/src/common/crypto.c index 2b2f3b311..53c261b14 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -644,31 +644,70 @@ int crypto_pk_private_sign(crypto_pk_env_t *env, unsigned char *from, int fromle } } -/* Given a private or public key pk, put a fingerprint of the - * public key into fp_out. +/* Encode the public portion of 'pk' into 'dest'. Return -1 on error, + * or the number of characters used on success. */ -int -crypto_pk_get_fingerprint(crypto_pk_env_t *pk, char *fp_out) +int crypto_pk_asn1_encode(crypto_pk_env_t *pk, char *dest, int dest_len) +{ + int len; + len = i2d_RSAPublicKey((RSA*)pk->key, NULL); + if (len < 0 || len > dest_len) + return -1; + len = i2d_RSAPublicKey((RSA*)pk->key, (unsigned char**)&dest); + if (len < 0) + return -1; + return len; +} + +/* Decode an ASN1-encoded public key from str. + */ +crypto_pk_env_t *crypto_pk_asn1_decode(const char *str, int len) +{ + RSA *rsa; + rsa = d2i_RSAPublicKey(NULL, (const unsigned char**)&str, len); + if (!rsa) + return NULL; /* XXXX log openssl error */ + return _crypto_new_pk_env_rsa(rsa); +} + +/* Given a private or public key pk, put a SHA1 hash of the public key into + * digest_out (must have 20 bytes of space). + */ +int crypto_pk_get_digest(crypto_pk_env_t *pk, char *digest_out) { unsigned char *buf, *bufp; - unsigned char digest[20]; int len; - int i; assert(pk->type == CRYPTO_PK_RSA); len = i2d_RSAPublicKey((RSA*)pk->key, NULL); if (len < 0) return -1; - if (len<FINGERPRINT_LEN+1) len = FINGERPRINT_LEN+1; buf = bufp = tor_malloc(len+1); len = i2d_RSAPublicKey((RSA*)pk->key, &bufp); if (len < 0) { free(buf); return -1; } - if (crypto_SHA_digest(buf, len, digest) < 0) { + if (crypto_SHA_digest(buf, len, digest_out) < 0) { free(buf); return -1; } + return 0; +} + +/* Given a private or public key pk, put a fingerprint of the + * public key into fp_out (must have at least FINGERPRINT_LEN+1 bytes of + * space). + */ +int +crypto_pk_get_fingerprint(crypto_pk_env_t *pk, char *fp_out) +{ + unsigned char *bufp; + unsigned char digest[20]; + unsigned char buf[FINGERPRINT_LEN+1]; + int i; + if (crypto_pk_get_digest(pk, digest)) { + return -1; + } bufp = buf; for (i = 0; i < 20; ++i) { sprintf(bufp,"%02X",digest[i]); @@ -681,7 +720,6 @@ crypto_pk_get_fingerprint(crypto_pk_env_t *pk, char *fp_out) assert(strlen(buf) == FINGERPRINT_LEN); assert(crypto_pk_check_fingerprint_syntax(buf)); strcpy(fp_out, buf); - free(buf); return 0; } @@ -1173,3 +1211,30 @@ base64_decode(char *dest, int destlen, const char *src, int srclen) ret += len; return ret; } + +static const char BASE32_CHARS[] = "abcdefghijklmnopqrstuvwxyz012345"; + +int +base32_encode(char *dest, int destlen, const char *src, int srclen) +{ + int nbits, i, bit, v, u; + nbits = srclen * 8; + + if ((nbits%5) != 0) + /* We need an even multiple of 5 bits. */ + return -1; + if ((nbits/5)+1 < destlen) + /* Not enough space. */ + return -1; + + for (i=0,bit=0; bit < nbits; ++i, bit+=5) { + /* set v to the 16-bit value starting at src[bits/8], 0-padded. */ + v = ((unsigned char)src[bit/8]) << 8; + if (bit+5<nbits) v += src[(bit/8)+1]; + /* set u to the 5-bit value at the bit'th bit of src. */ + u = (v >> (11-(bit%8))) & 0x1F; + dest[i] = BASE32_CHARS[u]; + } + dest[i] = '\0'; + return 0; +} diff --git a/src/common/crypto.h b/src/common/crypto.h index f371f416a..761a8d9fc 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -20,6 +20,8 @@ #define CRYPTO_SHA1_DIGEST 0 +#define CRYPTO_SHA1_DIGEST_LEN 20 + typedef struct crypto_pk_env_t crypto_pk_env_t; typedef struct crypto_cipher_env_t crypto_cipher_env_t; typedef struct crypto_digest_env_t crypto_digest_env_t; @@ -58,11 +60,15 @@ int crypto_pk_private_decrypt(crypto_pk_env_t *env, unsigned char *from, int fro int crypto_pk_private_sign(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to); int crypto_pk_public_checksig(crypto_pk_env_t *env, unsigned char *from, int fromlen, unsigned char *to); #define FINGERPRINT_LEN 49 +int crypto_pk_asn1_encode(crypto_pk_env_t *pk, char *dest, int dest_len); +crypto_pk_env_t *crypto_pk_asn1_decode(const char *str, int len); +int crypto_pk_get_digest(crypto_pk_env_t *pk, char *digest_out); int crypto_pk_get_fingerprint(crypto_pk_env_t *pk, char *fp_out); int crypto_pk_check_fingerprint_syntax(const char *s); int base64_encode(char *dest, int destlen, const char *src, int srclen); int base64_decode(char *dest, int destlen, const char *src, int srclen); +int base32_encode(char *dest, int destlen, const char *src, int srclen); /* Key negotiation */ typedef struct crypto_dh_env_st { diff --git a/src/or/test.c b/src/or/test.c index d992c0268..e329e73c3 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -408,6 +408,14 @@ test_crypto() test_streq(data3, "Ossifrage"); /*XXXX test failed signing*/ + /* Try encoding */ + crypto_free_pk_env(pk2); + pk2 = NULL; + i = crypto_pk_asn1_encode(pk1, data1, 1024); + test_assert(i>0); + pk2 = crypto_pk_asn1_decode(data1, i); + test_assert(crypto_pk_cmp_keys(pk1,pk2) == 0); + crypto_free_pk_env(pk1); crypto_free_pk_env(pk2); @@ -421,11 +429,18 @@ test_crypto() test_eq(j, 71); test_assert(data2[i] == '\0'); + /* Base32 tests */ + strcpy(data1, "5chrs"); + /* bit pattern is: [35 63 68 72 73] -> + * [00110101 01100011 01101000 01110010 01110011] + * By 5s: [00110 10101 10001 10110 10000 11100 10011 10011] + */ + i = base32_encode(data2, 9, data1, 5); + test_streq(data2, "gvrwq2tt"); free(data1); free(data2); free(data3); - } void |