aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2004-03-30 19:47:32 +0000
committerNick Mathewson <nickm@torproject.org>2004-03-30 19:47:32 +0000
commit6ea95488d2e2b519a33bd7c2f391b520a6dc6b97 (patch)
tree006e392500cc8439c4db421a6b29e0a002e860f9 /src
parentabcf3d934186d02e54253a57504138b900521ef7 (diff)
downloadtor-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.c83
-rw-r--r--src/common/crypto.h6
-rw-r--r--src/or/test.c17
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