gobjectification: 760fcafe: Patch from xanderw to have some more ci…

sadrul at pidgin.im sadrul at pidgin.im
Sat Mar 1 04:56:45 EST 2008


-----------------------------------------------------------------
Revision: 760fcafe15614b682f788c4d95abe462277ed964
Ancestor: 4744a54253d61080c6199372f133da2bc93254b8
Author: sadrul at pidgin.im
Date: 2008-03-01T09:52:34
Branch: im.pidgin.gobjectification
URL: http://d.pidgin.im/viewmtn/revision/info/760fcafe15614b682f788c4d95abe462277ed964

Added files:
        libpurple/des3cipher.c libpurple/des3cipher.h
        libpurple/hmaccipher.c libpurple/hmaccipher.h
        libpurple/rc4cipher.c libpurple/rc4cipher.h

ChangeLog: 

Patch from xanderw to have some more cipher stuff. References #35.

-------------- next part --------------
============================================================
--- libpurple/des3cipher.c	2dc0bfbbca01cb63e18a33b8e6e9016b5d2a0ad4
+++ libpurple/des3cipher.c	2dc0bfbbca01cb63e18a33b8e6e9016b5d2a0ad4
@@ -0,0 +1,468 @@
+/*
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+#include "des3cipher.h"
+#include "descipher.h"
+
+#include <string.h>
+
+/******************************************************************************
+ * Structs
+ *****************************************************************************/
+struct _PurpleDES3CipherPriv
+{
+	PurpleCipherBatchMode mode;
+	guchar iv[8];
+	/* First key for encryption */
+	PurpleCipher *key1;
+	/* Second key for decryption */
+	PurpleCipher *key2;
+	/* Third key for encryption */
+	PurpleCipher *key3;
+};
+
+/******************************************************************************
+ * Enums
+ *****************************************************************************/
+enum {
+	PROP_NONE,
+	PROP_BATCH_MODE,
+	PROP_IV,
+	PROP_KEY,
+	PROP_LAST,
+};
+
+/******************************************************************************
+ * Globals
+ *****************************************************************************/
+static GObjectClass *parent_class = NULL;
+
+/******************************************************************************
+ * Cipher Stuff
+ *****************************************************************************/
+/*
+ *  Fill a DES3 context with subkeys calculated from 3 64bit key.
+ *  Does not check parity bits, but simply ignore them.
+ *  Does not check for weak keys.
+ **/
+static void
+purple_des3_cipher_set_key(PurpleCipher *cipher, const guchar * key)
+{
+	PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher);
+
+	purple_cipher_set_key(PURPLE_CIPHER(des3_cipher->priv->key1), key +  0);
+	purple_cipher_set_key(PURPLE_CIPHER(des3_cipher->priv->key2), key +  8);
+	purple_cipher_set_key(PURPLE_CIPHER(des3_cipher->priv->key3), key + 16);
+
+	g_object_notify(G_OBJECT(des3_cipher), "key");
+}
+
+static gint
+purple_des3_cipher_ecb_encrypt(PurpleDES3Cipher *des3_cipher, const guchar data[],
+                 size_t len, guchar output[], size_t *outlen)
+{
+	int offset = 0;
+	int i = 0;
+	int tmp;
+	guint8 buf[8] = {0,0,0,0,0,0,0,0};
+
+	while (offset + 8 <= len) {
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key1),
+									data + offset, output + offset, 0);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key2),
+									output + offset, buf, 1);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key3),
+									buf, output + offset, 0);
+
+		offset += 8;
+	}
+
+	*outlen = len;
+
+	if (offset < len) {
+		*outlen += len - offset;
+		tmp = offset;
+		memset(buf, 0, 8);
+
+		while (tmp < len) {
+			buf[i++] = data[tmp];
+			tmp++;
+		}
+
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key1),
+									buf, output + offset, 0);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key2),
+									output + offset, buf, 1);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key3),
+									buf, output + offset, 0);
+	}
+
+	return 0;
+}
+
+static gint
+purple_des3_cipher_cbc_encrypt(PurpleDES3Cipher *des3_cipher, const guchar data[],
+							   size_t len, guchar output[], size_t *outlen)
+{
+	int offset = 0;
+	int i = 0;
+	int tmp;
+	guint8 buf[8];
+
+	memcpy(buf, des3_cipher->priv->iv, 8);
+
+	while (offset + 8 <= len) {
+		for (i = 0; i < 8; i++)
+			buf[i] ^= data[offset + i];
+
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key1),
+									buf, output + offset, 0);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key2),
+									output + offset, buf, 1);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key3),
+									buf, output + offset, 0);
+
+		memcpy(buf, output+offset, 8);
+		offset += 8;
+	}
+
+	*outlen = len;
+
+	if (offset < len) {
+		*outlen += len - offset;
+		tmp = offset;
+		i = 0;
+
+		while (tmp < len) {
+			buf[i++] ^= data[tmp];
+			tmp++;
+		}
+
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key1),
+									buf, output + offset, 0);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key2),
+									output + offset, buf, 1);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key3),
+									buf, output + offset, 0);
+	}
+
+	return 0;
+}
+
+static gint
+purple_des3_cipher_encrypt(PurpleCipher *cipher, const guchar data[],
+						   size_t len, guchar output[], size_t *outlen)
+{
+	PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher);
+
+	if (des3_cipher->priv->mode == PURPLE_CIPHER_BATCH_MODE_ECB) {
+		return purple_des3_cipher_ecb_encrypt(des3_cipher, data, len, output, outlen);
+	} else if (des3_cipher->priv->mode == PURPLE_CIPHER_BATCH_MODE_CBC) {
+		return purple_des3_cipher_cbc_encrypt(des3_cipher, data, len, output, outlen);
+	} else {
+		g_return_val_if_reached(0);
+	}
+
+	return 0;
+}
+
+static gint
+purple_des3_cipher_ecb_decrypt(PurpleDES3Cipher *des3_cipher, const guchar data[],
+                 size_t len, guchar output[], size_t *outlen)
+{
+	int offset = 0;
+	int i = 0;
+	int tmp;
+	guint8 buf[8] = {0,0,0,0,0,0,0,0};
+
+	while (offset + 8 <= len) {
+		/* NOTE: Apply key in reverse */
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key3),
+									data + offset, output + offset, 1);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key2),
+									output + offset, buf, 0);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key1),
+									buf, output + offset, 1);
+
+		offset += 8;
+	}
+
+	*outlen = len;
+
+	if (offset < len) {
+		*outlen += len - offset;
+		tmp = offset;
+		memset(buf, 0, 8);
+
+		while (tmp < len) {
+			buf[i++] = data[tmp];
+			tmp++;
+		}
+
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key3),
+									buf, output + offset, 1);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key2),
+									output + offset, buf, 0);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key1),
+									buf, output + offset, 1);
+	}
+
+	return 0;
+}
+
+static gint
+purple_des3_cipher_cbc_decrypt(PurpleDES3Cipher *des3_cipher, const guchar data[],
+                 size_t len, guchar output[], size_t *outlen)
+{
+	int offset = 0;
+	int i = 0;
+	int tmp;
+	guint8 buf[8] = {0,0,0,0,0,0,0,0};
+	guint8 link[8];
+
+	memcpy(link, des3_cipher->priv->iv, 8);
+
+	while (offset + 8 <= len) {
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key3),
+									data + offset, output + offset, 1);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key2),
+									output + offset, buf, 0);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key1),
+									buf, output + offset, 1);
+
+		for (i = 0; i < 8; i++)
+			output[offset + i] ^= link[i];
+
+		memcpy(link, data + offset, 8);
+
+		offset+=8;
+	}
+
+	*outlen = len;
+
+	if(offset<len) {
+		*outlen += len - offset;
+		tmp = offset;
+		memset(buf, 0, 8);
+		i = 0;
+
+		while(tmp<len) {
+			buf[i++] = data[tmp];
+			tmp++;
+		}
+
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key3),
+									buf, output + offset, 1);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key2),
+									output + offset, buf, 0);
+		purple_des_cipher_ecb_crypt(PURPLE_DES_CIPHER(des3_cipher->priv->key1),
+									buf, output + offset, 1);
+
+		for (i = 0; i < 8; i++)
+			output[offset + i] ^= link[i];
+	}
+
+	return 0;
+}
+
+static gint
+purple_des3_cipher_decrypt(PurpleCipher *cipher, const guchar data[],
+             size_t len, guchar output[], size_t *outlen)
+{
+	PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher);
+
+	if (des3_cipher->priv->mode == PURPLE_CIPHER_BATCH_MODE_ECB) {
+		return purple_des3_cipher_ecb_decrypt(des3_cipher, data, len, output, outlen);
+	} else if (des3_cipher->priv->mode == PURPLE_CIPHER_BATCH_MODE_CBC) {
+		return purple_des3_cipher_cbc_decrypt(des3_cipher, data, len, output, outlen);
+	} else {
+		g_return_val_if_reached(0);
+	}
+
+	return 0;
+}
+
+static void
+purple_des3_cipher_set_batch_mode(PurpleCipher *cipher, PurpleCipherBatchMode mode)
+{
+	PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher);
+
+	des3_cipher->priv->mode = mode;
+
+	g_object_notify(G_OBJECT(des3_cipher), "batchMode");
+}
+
+static PurpleCipherBatchMode
+purple_des3_cipher_get_batch_mode(PurpleCipher *cipher)
+{
+	PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher);
+
+	return des3_cipher->priv->mode;
+}
+
+static void
+purple_des3_cipher_set_iv(PurpleCipher *cipher, guchar *iv, size_t len)
+{
+	PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher);
+
+	g_return_if_fail(len == 8);
+
+	memcpy(des3_cipher->priv->iv, iv, len);
+
+	g_object_notify(G_OBJECT(des3_cipher), "iv");
+}
+
+/******************************************************************************
+ * Object Stuff
+ *****************************************************************************/
+static void
+purple_des3_cipher_get_property(GObject *obj, guint param_id, GValue *value,
+								GParamSpec *pspec)
+{
+	PurpleCipher *cipher = PURPLE_CIPHER(obj);
+
+	switch(param_id) {
+		case PROP_BATCH_MODE:
+			g_value_set_enum(value,
+							 purple_cipher_get_batch_mode(cipher));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+static void
+purple_des3_cipher_set_property(GObject *obj, guint param_id,
+								const GValue *value, GParamSpec *pspec)
+{
+	PurpleCipher *cipher = PURPLE_CIPHER(obj);
+	guchar *iv;
+
+	switch(param_id) {
+		case PROP_BATCH_MODE:
+			purple_cipher_set_batch_mode(cipher,
+										 g_value_get_enum(value));
+			break;
+		case PROP_IV:
+#warning I really dont like this...
+			iv = (guchar *)g_value_get_string(value);
+			purple_cipher_set_iv(cipher, iv, strlen((gchar*)iv));
+			break;
+		case PROP_KEY:
+			purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+static void
+purple_des3_cipher_finalize(GObject *obj) {
+	PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(obj);
+
+	g_object_unref(G_OBJECT(des3_cipher->priv->key1));
+	g_object_unref(G_OBJECT(des3_cipher->priv->key2));
+	g_object_unref(G_OBJECT(des3_cipher->priv->key3));
+
+	memset(des3_cipher->priv->iv, 0, sizeof(des3_cipher->priv->iv));
+
+	g_free(des3_cipher->priv);
+}
+
+static void
+purple_des3_cipher_class_init(PurpleDES3CipherClass *klass) {
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass);
+	GParamSpec *pspec;
+
+	parent_class = g_type_class_peek_parent(klass);
+
+	obj_class->finalize = purple_des3_cipher_finalize;
+	obj_class->get_property = purple_des3_cipher_get_property;
+	obj_class->set_property = purple_des3_cipher_set_property;
+
+	cipher_class->set_iv = purple_des3_cipher_set_iv;
+	cipher_class->encrypt = purple_des3_cipher_encrypt;
+	cipher_class->decrypt = purple_des3_cipher_decrypt;
+	cipher_class->set_key = purple_des3_cipher_set_key;
+	cipher_class->set_batch_mode = purple_des3_cipher_set_batch_mode;
+	cipher_class->get_batch_mode = purple_des3_cipher_get_batch_mode;
+
+	pspec = g_param_spec_enum("batchMode", "batchMode", "batchMode",
+							  PURPLE_TYPE_CIPHER_BATCH_MODE, 0,
+							  G_PARAM_READWRITE);
+	g_object_class_install_property(obj_class, PROP_BATCH_MODE, pspec);
+
+	pspec = g_param_spec_string("iv", "iv", "iv", NULL,
+								G_PARAM_WRITABLE);
+	g_object_class_install_property(obj_class, PROP_IV, pspec);
+
+	pspec = g_param_spec_string("key", "key", "key", NULL,
+								G_PARAM_WRITABLE);
+	g_object_class_install_property(obj_class, PROP_KEY, pspec);
+}
+
+static void
+purple_des3_cipher_init(PurpleCipher *cipher) {
+	PurpleDES3Cipher *des3_cipher = PURPLE_DES3_CIPHER(cipher);
+
+	des3_cipher->priv = g_new0(PurpleDES3CipherPriv, 1);
+
+	des3_cipher->priv->key1 = purple_des_cipher_new();
+	des3_cipher->priv->key2 = purple_des_cipher_new();
+	des3_cipher->priv->key3 = purple_des_cipher_new();
+}
+
+/******************************************************************************
+ * API
+ *****************************************************************************/
+GType
+purple_des3_cipher_get_gtype(void) {
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo info = {
+			sizeof(PurpleDES3CipherClass),
+			NULL,
+			NULL,
+			(GClassInitFunc)purple_des3_cipher_class_init,
+			NULL,
+			NULL,
+			sizeof(PurpleDES3Cipher),
+			0,
+			(GInstanceInitFunc)purple_des3_cipher_init,
+			NULL
+		};
+
+		type = g_type_register_static(PURPLE_TYPE_CIPHER,
+									  "PurpleDES3Cipher",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+PurpleCipher *
+purple_des3_cipher_new(void) {
+	return g_object_new(PURPLE_TYPE_DES3_CIPHER, NULL);
+}
============================================================
--- libpurple/des3cipher.h	1cf98e02bab972f08aceb15845f8509861befe74
+++ libpurple/des3cipher.h	1cf98e02bab972f08aceb15845f8509861befe74
@@ -0,0 +1,71 @@
+/**
+ * @file des3cipher.h Purple Triple-DES Cipher
+ * @ingroup core
+ */
+
+/* purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+#ifndef PURPLE_DES3_CIPHER_H
+#define PURPLE_DES3_CIPHER_H
+
+#include <cipher.h>
+
+#define PURPLE_TYPE_DES3_CIPHER				(purple_des3_cipher_get_gtype())
+#define PURPLE_DES3_CIPHER(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_DES3_CIPHER, PurpleDES3Cipher))
+#define PURPLE_DES3_CIPHER_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_DES3_CIPHER, PurpleDES3CipherClass))
+#define PURPLE_IS_DES3_CIPHER(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_DES3_CIPHER))
+#define PURPLE_IS_DES3_CIPHER_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_DES3_CIPHER))
+#define PURPLE_DES3_CIPHER_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_DES3_CIPHER, PurpleDES3CipherClass))
+
+typedef struct _PurpleDES3Cipher			PurpleDES3Cipher;
+typedef struct _PurpleDES3CipherPriv		PurpleDES3CipherPriv;
+typedef struct _PurpleDES3CipherClass		PurpleDES3CipherClass;
+
+struct _PurpleDES3Cipher {
+	PurpleCipher gparent;
+
+	PurpleDES3CipherPriv *priv;
+
+	void (*_purple_reserved1)(void);
+	void (*_purple_reserved2)(void);
+	void (*_purple_reserved3)(void);
+	void (*_purple_reserved4)(void);
+};
+
+struct _PurpleDES3CipherClass {
+	PurpleCipherClass gparent;
+
+	void (*_purple_reserved1)(void);
+	void (*_purple_reserved2)(void);
+	void (*_purple_reserved3)(void);
+	void (*_purple_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType purple_des3_cipher_get_gtype(void);
+
+PurpleCipher *purple_des3_cipher_new(void);
+
+G_END_DECLS
+
+#endif /* PURPLE_DES3_CIPHER_H */
+
============================================================
--- libpurple/hmaccipher.c	44ad9ef92f1f5abf7187c21d1881cc490986de28
+++ libpurple/hmaccipher.c	44ad9ef92f1f5abf7187c21d1881cc490986de28
@@ -0,0 +1,319 @@
+/*
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+#include "hmaccipher.h"
+
+#include <string.h>
+
+/*******************************************************************************
+ * Structs
+ ******************************************************************************/
+struct _PurpleHMACCipherPriv {
+	PurpleCipher *hash;
+	int blocksize;
+	guchar *opad;
+};
+
+/******************************************************************************
+ * Enums
+ *****************************************************************************/
+enum {
+	PROP_NONE,
+	PROP_BLOCK_SIZE,
+	PROP_HASH,
+	PROP_KEY,
+	PROP_LAST,
+};
+
+/*******************************************************************************
+ * Globals
+ ******************************************************************************/
+static GObjectClass *parent_class = NULL;
+
+/*******************************************************************************
+ * Cipher Stuff
+ ******************************************************************************/
+static void
+purple_hmac_cipher_reset(PurpleCipher *cipher)
+{
+	PurpleHMACCipher *hmac_cipher = PURPLE_HMAC_CIPHER(cipher);
+
+	if(hmac_cipher->priv->hash)
+	{
+		g_object_unref(G_OBJECT(hmac_cipher->priv->hash));
+		hmac_cipher->priv->hash = NULL;
+	}
+
+	hmac_cipher->priv->blocksize = 0;
+
+	if(hmac_cipher->priv->opad)
+	{
+		g_free(hmac_cipher->priv->opad);
+		hmac_cipher->priv->opad = NULL;
+	}
+}
+
+static void
+purple_hmac_cipher_append(PurpleCipher *cipher, const guchar *data, size_t len)
+{
+	PurpleHMACCipher *hmac_cipher = PURPLE_HMAC_CIPHER(cipher);
+
+	g_return_if_fail(hmac_cipher->priv->hash);
+
+	purple_cipher_append(hmac_cipher->priv->hash, data, len);
+}
+
+static gboolean
+purple_hmac_cipher_digest(PurpleCipher *cipher, size_t in_len, guchar *out, size_t *out_len)
+{
+	PurpleHMACCipher *hmac_cipher = PURPLE_HMAC_CIPHER(cipher);
+	PurpleCipher *hash = hmac_cipher->priv->hash;
+	guchar *inner_hash;
+	size_t hash_len;
+	gboolean result;
+
+	g_return_val_if_fail(hash, FALSE);
+
+	inner_hash = g_malloc(100); /* TODO: Should be enough for now... */
+	result = purple_cipher_digest(hash, 100, inner_hash, &hash_len);
+
+	purple_cipher_reset(hash);
+
+	purple_cipher_append(hash, hmac_cipher->priv->opad, hmac_cipher->priv->blocksize);
+	purple_cipher_append(hash, inner_hash, hash_len);
+
+	g_free(inner_hash);
+
+	result = result && purple_cipher_digest(hash, in_len, out, out_len);
+
+	return result;
+}
+
+static void
+purple_hmac_cipher_set_key_with_len(PurpleCipher *cipher, const guchar * key, size_t key_len)
+{
+	PurpleHMACCipher *hmac_cipher = PURPLE_HMAC_CIPHER(cipher);
+	int blocksize, i;
+	guchar *ipad;
+	guchar *full_key;
+
+	g_return_if_fail(hmac_cipher->priv->hash);
+
+	g_free(hmac_cipher->priv->opad);
+
+	blocksize = hmac_cipher->priv->blocksize;
+	ipad = g_malloc(blocksize);
+	hmac_cipher->priv->opad = g_malloc(blocksize);
+
+	if (key_len > blocksize) {
+		purple_cipher_reset(hmac_cipher->priv->hash);
+		purple_cipher_append(hmac_cipher->priv->hash, key, key_len);
+		full_key = g_malloc(100); /* TODO: Should be enough for now... */
+		purple_cipher_digest(hmac_cipher->priv->hash, 100, full_key, &key_len);
+	} else
+		full_key = g_memdup(key, key_len);
+
+    if (key_len < blocksize) {
+		full_key = g_realloc(full_key, blocksize);
+		memset(full_key + key_len, 0, blocksize - key_len);
+    }
+
+	for(i = 0; i < blocksize; i++) {
+		ipad[i] = 0x36 ^ full_key[i];
+		hmac_cipher->priv->opad[i] = 0x5c ^ full_key[i];
+	}
+
+	g_free(full_key);
+
+	purple_cipher_reset(hmac_cipher->priv->hash);
+	purple_cipher_append(hmac_cipher->priv->hash, ipad, blocksize);
+	g_free(ipad);
+
+	g_object_notify(G_OBJECT(hmac_cipher), "key");
+}
+
+static void
+purple_hmac_cipher_set_key(PurpleCipher *cipher, const guchar *key)
+{
+	purple_hmac_cipher_set_key_with_len(cipher, key, strlen((char *)key));
+}
+
+static size_t
+purple_hmac_cipher_get_block_size(PurpleCipher *cipher)
+{
+	PurpleHMACCipher *hmac_cipher = PURPLE_HMAC_CIPHER(cipher);
+
+	return hmac_cipher->priv->blocksize;
+}
+
+static void
+purple_hmac_cipher_set_hash(PurpleCipher *cipher,
+							PurpleCipher *hash)
+{
+	PurpleHMACCipher *hmac_cipher = PURPLE_HMAC_CIPHER(cipher);
+
+	hmac_cipher->priv->hash = g_object_ref_sink(hash);
+	hmac_cipher->priv->blocksize = purple_cipher_get_block_size(hash);
+
+	g_object_notify(G_OBJECT(hmac_cipher), "hash");
+}
+
+static PurpleCipher *
+purple_hmac_cipher_get_hash(PurpleCipher *cipher)
+{
+	PurpleHMACCipher *hmac_cipher = PURPLE_HMAC_CIPHER(cipher);
+
+	return hmac_cipher->priv->hash;
+}
+
+/******************************************************************************
+ * Object Stuff
+ *****************************************************************************/
+static void
+purple_hmac_cipher_set_property(GObject *obj, guint param_id,
+								const GValue *value,
+								GParamSpec *pspec)
+{
+	PurpleCipher *cipher = PURPLE_CIPHER(obj);
+
+	switch(param_id) {
+		case PROP_HASH:
+			purple_cipher_set_hash(cipher, g_value_get_object(value));
+			break;
+		case PROP_KEY:
+			purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+static void
+purple_hmac_cipher_get_property(GObject *obj, guint param_id, GValue *value,
+								GParamSpec *pspec)
+{
+	PurpleCipher *cipher = PURPLE_CIPHER(obj);
+
+	switch(param_id) {
+		case PROP_BLOCK_SIZE:
+			g_value_set_int(value,
+							purple_cipher_get_block_size(cipher));
+			break;
+		case PROP_HASH:
+			g_value_set_object(value,
+							   purple_cipher_get_hash(cipher));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+static void
+purple_hmac_cipher_finalize(GObject *obj) {
+	PurpleCipher *cipher = PURPLE_CIPHER(obj);
+	PurpleHMACCipher *hmac_cipher = PURPLE_HMAC_CIPHER(obj);
+
+	/* reset the cipher so we don't leave any data around... */
+	purple_hmac_cipher_reset(cipher);
+
+	g_free(hmac_cipher->priv);
+}
+
+static void
+purple_hmac_cipher_class_init(PurpleHMACCipherClass *klass) {
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass);
+	GParamSpec *pspec;
+
+	parent_class = g_type_class_peek_parent(klass);
+
+	obj_class->finalize = purple_hmac_cipher_finalize;
+	obj_class->get_property = purple_hmac_cipher_get_property;
+	obj_class->set_property = purple_hmac_cipher_set_property;
+
+	cipher_class->reset = purple_hmac_cipher_reset;
+	cipher_class->append = purple_hmac_cipher_append;
+	cipher_class->digest = purple_hmac_cipher_digest;
+
+	cipher_class->set_key = purple_hmac_cipher_set_key;
+	cipher_class->set_key_with_len = purple_hmac_cipher_set_key_with_len;
+	cipher_class->get_block_size = purple_hmac_cipher_get_block_size;
+	cipher_class->set_hash = purple_hmac_cipher_set_hash;
+	cipher_class->get_hash = purple_hmac_cipher_get_hash;
+
+	pspec = g_param_spec_int("blockSize", "blockSize", "blockSize",
+							 G_MININT, G_MAXINT, 0,
+							 G_PARAM_READABLE);
+	g_object_class_install_property(obj_class, PROP_BLOCK_SIZE, pspec);
+
+	pspec = g_param_spec_object("hash", "hash", "hash", PURPLE_TYPE_CIPHER,
+								G_PARAM_READWRITE);
+	g_object_class_install_property(obj_class, PROP_HASH, pspec);
+
+	pspec = g_param_spec_string("key", "key", "key", NULL,
+								G_PARAM_WRITABLE);
+	g_object_class_install_property(obj_class, PROP_KEY, pspec);
+}
+
+static void
+purple_hmac_cipher_init(PurpleCipher *cipher) {
+	PurpleHMACCipher *hmac_cipher = PURPLE_HMAC_CIPHER(cipher);
+
+	hmac_cipher->priv = g_new0(PurpleHMACCipherPriv, 1);
+
+	purple_hmac_cipher_reset(cipher);
+}
+
+/******************************************************************************
+ * API
+ *****************************************************************************/
+GType
+purple_hmac_cipher_get_gtype(void) {
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo info = {
+			sizeof(PurpleHMACCipherClass),
+			NULL,
+			NULL,
+			(GClassInitFunc)purple_hmac_cipher_class_init,
+			NULL,
+			NULL,
+			sizeof(PurpleHMACCipher),
+			0,
+			(GInstanceInitFunc)purple_hmac_cipher_init,
+			NULL,
+		};
+
+		type = g_type_register_static(PURPLE_TYPE_CIPHER,
+									  "PurpleHMACCipher",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+PurpleCipher *
+purple_hmac_cipher_new(void) {
+	return g_object_new(PURPLE_TYPE_HMAC_CIPHER, NULL);
+}
============================================================
--- libpurple/hmaccipher.h	d298ee6316a0762841c2072d0f3d0d94da99e2d4
+++ libpurple/hmaccipher.h	d298ee6316a0762841c2072d0f3d0d94da99e2d4
@@ -0,0 +1,70 @@
+/**
+ * @file hmaccipher.h Purple HMAC Cipher
+ * @ingroup core
+ */
+
+/* purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+#ifndef PURPLE_HMAC_CIPHER_H
+#define PURPLE_HMAC_CIPHER_H
+
+#include <cipher.h>
+
+#define PURPLE_TYPE_HMAC_CIPHER				(purple_hmac_cipher_get_gtype())
+#define PURPLE_HMAC_CIPHER(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipher))
+#define PURPLE_HMAC_CIPHER_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipherClass))
+#define PURPLE_IS_HMAC_CIPHER(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_HMAC_CIPHER))
+#define PURPLE_IS_HMAC_CIPHER_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_HMAC_CIPHER))
+#define PURPLE_HMAC_CIPHER_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipherClass))
+
+typedef struct _PurpleHMACCipher				PurpleHMACCipher;
+typedef struct _PurpleHMACCipherPriv			PurpleHMACCipherPriv;
+typedef struct _PurpleHMACCipherClass			PurpleHMACCipherClass;
+
+struct _PurpleHMACCipher {
+	PurpleCipher gparent;
+
+	PurpleHMACCipherPriv *priv;
+
+	void (*_purple_reserved1)(void);
+	void (*_purple_reserved2)(void);
+	void (*_purple_reserved3)(void);
+	void (*_purple_reserved4)(void);
+};
+
+struct _PurpleHMACCipherClass {
+	PurpleCipherClass gparent;
+
+	void (*_purple_reserved1)(void);
+	void (*_purple_reserved2)(void);
+	void (*_purple_reserved3)(void);
+	void (*_purple_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType purple_hmac_cipher_get_gtype(void);
+
+PurpleCipher *purple_hmac_cipher_new(void);
+
+G_END_DECLS
+
+#endif /* PURPLE_HMAC_CIPHER_H */
============================================================
--- libpurple/rc4cipher.c	f24404ddc7191c7948a56016335f87f437af929e
+++ libpurple/rc4cipher.c	f24404ddc7191c7948a56016335f87f437af929e
@@ -0,0 +1,269 @@
+/*
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+#include "rc4cipher.h"
+
+/*******************************************************************************
+ * Structs
+ ******************************************************************************/
+struct _PurpleRC4CipherPriv {
+  guchar state[256];
+  guchar x;
+  guchar y;
+  gint key_len;
+};
+
+/******************************************************************************
+ * Enums
+ *****************************************************************************/
+enum {
+	PROP_ZERO,
+	PROP_KEY_LEN,
+	PROP_KEY,
+	PROP_LAST,
+};
+
+/******************************************************************************
+ * Globals
+ *****************************************************************************/
+static GObjectClass *parent_class = NULL;
+
+/******************************************************************************
+ * Cipher Stuff
+ *****************************************************************************/
+static void
+purple_rc4_cipher_reset(PurpleCipher *cipher) {
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher);
+	guint i;
+
+	for(i = 0; i < 256; i++)
+		rc4_cipher->priv->state[i] = i;
+	rc4_cipher->priv->x = 0;
+	rc4_cipher->priv->y = 0;
+
+	/* default is 5 bytes (40bit key) */
+	rc4_cipher->priv->key_len = 5;
+}
+
+static void
+purple_rc4_cipher_set_key (PurpleCipher *cipher, const guchar * key) {
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher);
+	guchar *state;
+	guchar temp_swap;
+	guchar x, y;
+	guint i;
+
+	x = 0;
+	y = 0;
+	state = &rc4_cipher->priv->state[0];
+	for(i = 0; i < 256; i++)
+	{
+		y = (key[x] + state[i] + y) % 256;
+		temp_swap = state[i];
+		state[i] = state[y];
+		state[y] = temp_swap;
+		x = (x + 1) % rc4_cipher->priv->key_len;
+	}
+
+	g_object_notify(G_OBJECT(rc4_cipher), "key");
+}
+
+
+static size_t
+purple_rc4_cipher_get_key_size (PurpleCipher *cipher)
+{
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher);
+
+	return rc4_cipher->priv->key_len;
+}
+
+
+static gint
+purple_rc4_cipher_encrypt(PurpleCipher *cipher, const guchar data[], size_t len,
+						  guchar output[], size_t *outlen)
+{
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher);
+	guchar temp_swap;
+	guchar x, y, z;
+	guchar *state;
+	guint i;
+
+	x = rc4_cipher->priv->x;
+	y = rc4_cipher->priv->y;
+	state = &rc4_cipher->priv->state[0];
+
+	for(i = 0; i < len; i++)
+	{
+		x = (x + 1) % 256;
+		y = (state[x] + y) % 256;
+		temp_swap = state[x];
+		state[x] = state[y];
+		state[y] = temp_swap;
+		z = state[x] + (state[y]) % 256;
+		output[i] = data[i] ^ state[z];
+	}
+	rc4_cipher->priv->x = x;
+	rc4_cipher->priv->y = y;
+	if(outlen)
+		*outlen = len;
+
+	return 0;
+}
+
+/******************************************************************************
+ * Object Stuff
+ *****************************************************************************/
+static void
+purple_rc4_cipher_set_property(GObject *obj, guint param_id,
+							   const GValue *value, GParamSpec *pspec)
+{
+	PurpleCipher *cipher = PURPLE_CIPHER(obj);
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(obj);
+
+	switch(param_id) {
+		case PROP_KEY_LEN:
+			purple_rc4_cipher_set_key_len(rc4_cipher, g_value_get_int(value));
+			break;
+		case PROP_KEY:
+			purple_cipher_set_key(cipher, (guchar *)g_value_get_string(value));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+static void
+purple_rc4_cipher_get_property(GObject *obj, guint param_id, GValue *value,
+							   GParamSpec *pspec)
+{
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(obj);
+
+	switch(param_id) {
+		case PROP_KEY_LEN:
+			g_value_set_int(value,
+							purple_rc4_cipher_get_key_len(rc4_cipher));
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
+			break;
+	}
+}
+
+static void
+purple_rc4_cipher_finalize(GObject *obj) {
+	PurpleCipher *cipher = PURPLE_CIPHER(obj);
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(obj);
+
+	/* reset the cipher so we don't leave any data around... */
+	purple_rc4_cipher_reset(cipher);
+
+	g_free(rc4_cipher->priv);
+}
+
+static void
+purple_rc4_cipher_class_init(PurpleRC4CipherClass *klass) {
+	GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+	PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass);
+	GParamSpec *pspec = NULL;
+
+	parent_class = g_type_class_peek_parent(klass);
+
+	obj_class->set_property = purple_rc4_cipher_set_property;
+	obj_class->get_property = purple_rc4_cipher_get_property;
+	obj_class->finalize = purple_rc4_cipher_finalize;
+
+	cipher_class->reset = purple_rc4_cipher_reset;
+	cipher_class->encrypt = purple_rc4_cipher_encrypt;
+	cipher_class->set_key = purple_rc4_cipher_set_key;
+	cipher_class->get_key_size = purple_rc4_cipher_get_key_size;
+
+	pspec = g_param_spec_int("key_len", "key_len", "key_len",
+							 G_MININT, G_MAXINT, 0,
+							 G_PARAM_READWRITE);
+	g_object_class_install_property(obj_class, PROP_KEY_LEN, pspec);
+
+	pspec = g_param_spec_string("key", "key", "key", NULL,
+								G_PARAM_WRITABLE);
+	g_object_class_install_property(obj_class, PROP_KEY, pspec);
+}
+
+static void
+purple_rc4_cipher_init(PurpleCipher *cipher) {
+	PurpleRC4Cipher *rc4_cipher = PURPLE_RC4_CIPHER(cipher);
+
+	rc4_cipher->priv = g_new0(PurpleRC4CipherPriv, 1);
+
+	purple_rc4_cipher_reset(cipher);
+}
+
+/******************************************************************************
+ * API
+ *****************************************************************************/
+GType
+purple_rc4_cipher_get_gtype(void) {
+	static GType type = 0;
+
+	if(type == 0) {
+		static const GTypeInfo info = {
+			sizeof(PurpleRC4CipherClass),
+			NULL,
+			NULL,
+			(GClassInitFunc)purple_rc4_cipher_class_init,
+			NULL,
+			NULL,
+			sizeof(PurpleRC4Cipher),
+			0,
+			(GInstanceInitFunc)purple_rc4_cipher_init,
+			NULL,
+		};
+
+		type = g_type_register_static(PURPLE_TYPE_CIPHER,
+									  "PurpleRC4Cipher",
+									  &info, 0);
+	}
+
+	return type;
+}
+
+PurpleCipher *
+purple_rc4_cipher_new(void) {
+	return g_object_new(PURPLE_TYPE_RC4_CIPHER, NULL);
+}
+
+void
+purple_rc4_cipher_set_key_len(PurpleRC4Cipher *rc4_cipher,
+							  gint key_len)
+{
+	g_return_if_fail(PURPLE_IS_RC4_CIPHER(rc4_cipher));
+
+	rc4_cipher->priv->key_len = key_len;
+
+	g_object_notify(G_OBJECT(rc4_cipher), "key_len");
+}
+
+gint
+purple_rc4_cipher_get_key_len(PurpleRC4Cipher *rc4_cipher)
+{
+	g_return_val_if_fail(PURPLE_IS_RC4_CIPHER(rc4_cipher), 0);
+
+	return rc4_cipher->priv->key_len;
+}
============================================================
--- libpurple/rc4cipher.h	98a9b8b7fd4ab55e84015c408c5014611f6c7be4
+++ libpurple/rc4cipher.h	98a9b8b7fd4ab55e84015c408c5014611f6c7be4
@@ -0,0 +1,75 @@
+/**
+ * @file rc4cipher.h Purple RC4 Cipher
+ * @ingroup core
+ */
+
+/* purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+#ifndef PURPLE_RC4_CIPHER_H
+#define PURPLE_RC4_CIPHER_H
+
+#include <cipher.h>
+
+#define PURPLE_TYPE_RC4_CIPHER				(purple_rc4_cipher_get_gtype())
+#define PURPLE_RC4_CIPHER(obj)				(G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4Cipher))
+#define PURPLE_RC4_CIPHER_CLASS(klass)		(G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherClass))
+#define PURPLE_IS_RC4_CIPHER(obj)			(G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_RC4_CIPHER))
+#define PURPLE_IS_RC4_CIPHER_CLASS(klass)	(G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_RC4_CIPHER))
+#define PURPLE_RC4_CIPHER_GET_CLASS(obj)	(G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_RC4_CIPHER, PurpleRC4CipherClass))
+
+typedef struct _PurpleRC4Cipher				PurpleRC4Cipher;
+typedef struct _PurpleRC4CipherPriv			PurpleRC4CipherPriv;
+typedef struct _PurpleRC4CipherClass		PurpleRC4CipherClass;
+
+struct _PurpleRC4Cipher {
+	PurpleCipher gparent;
+
+	PurpleRC4CipherPriv *priv;
+
+	void (*_purple_reserved1)(void);
+	void (*_purple_reserved2)(void);
+	void (*_purple_reserved3)(void);
+	void (*_purple_reserved4)(void);
+};
+
+struct _PurpleRC4CipherClass {
+	PurpleCipherClass gparent;
+
+	void (*_purple_reserved1)(void);
+	void (*_purple_reserved2)(void);
+	void (*_purple_reserved3)(void);
+	void (*_purple_reserved4)(void);
+};
+
+G_BEGIN_DECLS
+
+GType purple_rc4_cipher_get_gtype(void);
+
+PurpleCipher *purple_rc4_cipher_new(void);
+
+gint purple_rc4_cipher_get_key_len(PurpleRC4Cipher *rc4_cipher);
+void purple_rc4_cipher_set_key_len(PurpleRC4Cipher *rc4_cipher, gint key_len);
+
+G_END_DECLS
+
+#endif /* PURPLE_RC4_CIPHER_H */
+
+


More information about the Commits mailing list