Esempio n. 1
0
/**
 * mega_aes_key_get_enc_ubase64:
 * @aes_key: a #MegaAesKey
 * @enc_key: Encryption key.
 *
 * Get UBase64 encoded key data encrypted with #enc_key.
 *
 * Returns: UBase64 encoded string.
 */
gchar* mega_aes_key_get_enc_ubase64(MegaAesKey* aes_key, MegaAesKey* enc_key)
{
    g_return_val_if_fail(MEGA_IS_AES_KEY(aes_key), NULL);
    g_return_val_if_fail(MEGA_IS_AES_KEY(enc_key), NULL);
    g_return_val_if_fail(aes_key->priv->loaded, NULL);

    return mega_aes_key_encrypt(enc_key, aes_key->priv->key, 16);
}
Esempio n. 2
0
/**
 * mega_aes_key_get_enc_binary:
 * @aes_key: a #MegaAesKey
 * @enc_key: Encryption key.
 *
 * Get 16 byte AES key data encrypted with #enc_key.
 *
 * Returns: (element-type guint8) (array fixed-size=16) (transfer full): Key
 * data
 */
guchar* mega_aes_key_get_enc_binary(MegaAesKey* aes_key, MegaAesKey* enc_key)
{
    guchar cipher_key[16];

    g_return_val_if_fail(MEGA_IS_AES_KEY(aes_key), NULL);
    g_return_val_if_fail(MEGA_IS_AES_KEY(enc_key), NULL);
    g_return_val_if_fail(aes_key->priv->loaded, NULL);

    mega_aes_key_encrypt_raw(enc_key, aes_key->priv->key, cipher_key, 16);

    return g_memdup(cipher_key, 16);
}
Esempio n. 3
0
/**
 * mega_aes_key_load_enc_binary:
 * @aes_key: a #MegaAesKey
 * @data: (element-type guint8) (array fixed-size=16): 16 byte AES key buffer
 * @dec_key: Decryption key
 *
 * Initialize key from #data.
 */
void mega_aes_key_load_enc_binary(MegaAesKey* aes_key, const guchar* data, MegaAesKey* dec_key)
{
    guchar plain_key[16];

    g_return_if_fail(MEGA_IS_AES_KEY(aes_key));
    g_return_if_fail(data != NULL);
    g_return_if_fail(MEGA_IS_AES_KEY(dec_key));

    mega_aes_key_decrypt_raw(dec_key, data, plain_key, 16);

    mega_aes_key_load_binary(aes_key, plain_key);
}
Esempio n. 4
0
/**
 * mega_aes_key_decrypt:
 * @aes_key: a #MegaAesKey
 * @cipher: UBase64 encoded ciphertext.
 *
 * Decrypt UBase64 encoded 16-byte aligned ciphertext into binary plaintext data.
 *
 * Returns: (transfer full): Binary plaintext data.
 */
GBytes* mega_aes_key_decrypt(MegaAesKey* aes_key, const gchar* cipher)
{
    gsize cipherlen = 0;
    guchar* cipher_raw;
    guchar* plain;

    g_return_val_if_fail(MEGA_IS_AES_KEY(aes_key), NULL);
    g_return_val_if_fail(cipher != NULL, NULL);

    cipher_raw = mega_base64urldecode(cipher, &cipherlen);
    if (cipher_raw == NULL)
        return NULL;

    if (cipherlen == 0)
    {
        g_free(cipher_raw);
        return NULL;
    }

    if (cipherlen % 16 != 0)
    {
        g_free(cipher_raw);
        return NULL;
    }

    plain = g_malloc0(cipherlen);
    mega_aes_key_decrypt_raw(aes_key, cipher_raw, plain, cipherlen);
    g_free(cipher_raw);

    return g_bytes_new_take(plain, cipherlen);
}
Esempio n. 5
0
/**
 * mega_aes_key_get_binary:
 * @aes_key: a #MegaAesKey
 *
 * Get 16 byte AES key data.
 *
 * Returns: (element-type guint8) (array fixed-size=16) (transfer full): Key
 * data
 */
guchar* mega_aes_key_get_binary(MegaAesKey* aes_key)
{
    g_return_val_if_fail(MEGA_IS_AES_KEY(aes_key), NULL);
    g_return_val_if_fail(aes_key->priv->loaded, NULL);

    return g_memdup(aes_key->priv->key, 16);
}
Esempio n. 6
0
/**
 * mega_aes_key_decrypt_cbc:
 * @aes_key: a #MegaAesKey
 * @cipher: UBase64 encoded ciphertext.
 *
 * Decrypt UBase64 encoded ciphertext blocks using AES key in CBC mode with zero IV.
 *
 * Returns: (transfer full): UBase64 encoded ciphertext.
 */
GBytes* mega_aes_key_decrypt_cbc(MegaAesKey* aes_key, const gchar* cipher)
{
    guchar iv[AES_BLOCK_SIZE] = {0};
    guchar* cipher_raw;
    guchar* plain;
    gsize cipherlen = 0;

    g_return_val_if_fail(MEGA_IS_AES_KEY(aes_key), NULL);
    g_return_val_if_fail(cipher != NULL, NULL);

    cipher_raw = mega_base64urldecode(cipher, &cipherlen);
    if (cipher_raw == NULL)
        return NULL;

    if (cipherlen % 16 != 0)
    {
        g_free(cipher_raw);
        return NULL;
    }

    plain = g_malloc0(cipherlen + 1);
    AES_cbc_encrypt(cipher_raw, plain, cipherlen, &aes_key->priv->dec_key, iv, 0);
    g_free(cipher_raw);

    return g_bytes_new_take(plain, cipherlen);
}
Esempio n. 7
0
/**
 * mega_aes_key_get_ubase64:
 * @aes_key: a #MegaAesKey
 *
 * Get UBase64 encoded key data.
 *
 * Returns: UBase64 encoded string.
 */
gchar* mega_aes_key_get_ubase64(MegaAesKey* aes_key)
{
    g_return_val_if_fail(MEGA_IS_AES_KEY(aes_key), NULL);
    g_return_val_if_fail(aes_key->priv->loaded, NULL);

    return mega_base64urlencode(aes_key->priv->key, 16);
}
Esempio n. 8
0
/**
 * mega_aes_key_make_username_hash:
 * @aes_key: a #MegaAesKey
 * @username: E-mail
 *
 * Generate username hash (uh paraemter for 'us' API call) used for authentication to mega.nz.
 *
 * Returns: Username hash string
 */
gchar* mega_aes_key_make_username_hash(MegaAesKey* aes_key, const gchar* username)
{
    gchar* username_lower;

    g_return_val_if_fail(MEGA_IS_AES_KEY(aes_key), NULL);
    g_return_val_if_fail(username != NULL, NULL);

    username_lower = g_ascii_strdown(username, -1);

    gint l, i;
    guchar hash[16] = {0}, hash_tmp[16], oh[8];

    for (i = 0, l = strlen(username_lower); i < l; i++)
        hash[i % 16] ^= username_lower[i];

    for (i = 16384; i--; )
    {
        AES_encrypt(hash, hash_tmp, &aes_key->priv->enc_key);
        memcpy(hash, hash_tmp, 16);
    }

    memcpy(oh, hash, 4);
    memcpy(oh + 4, hash + 8, 4);

    g_free(username_lower);

    return mega_base64urlencode(oh, 8);
}
Esempio n. 9
0
/**
 * mega_aes_key_generate_from_password:
 * @aes_key: a #MegaAesKey
 * @password:
 *
 * Initialize key from plaintext password string. (mega.nz algorithm)
 */
void mega_aes_key_generate_from_password(MegaAesKey* aes_key, const gchar* password)
{
    g_return_if_fail(MEGA_IS_AES_KEY(aes_key));
    g_return_if_fail(password != NULL);

    guchar pkey[16] = {0x93, 0xC4, 0x67, 0xE3, 0x7D, 0xB0, 0xC7, 0xA4, 0xD1, 0xBE, 0x3F, 0x81, 0x01, 0x52, 0xCB, 0x56};
    gint off, r;
    gint len;

    len = strlen(password);

    for (r = 65536; r--; )
    {
        for (off = 0; off < len; off += 16)
        {
            AES_KEY k;
            guchar key[16] = {0}, pkey_tmp[16];
            strncpy(key, password + off, 16);

            AES_set_encrypt_key(key, 128, &k);
            AES_encrypt(pkey, pkey_tmp, &k);
            memcpy(pkey, pkey_tmp, 16);
        }
    }

    mega_aes_key_load_binary(aes_key, pkey);
}
Esempio n. 10
0
/**
 * mega_aes_key_encrypt_ctr:
 * @aes_key: a #MegaAesKey
 * @from: (in) (element-type guint8) (array length=len): Plaintext input data
 * @to: (out caller-allocates) (element-type guint8) (array length=len): Ciphertext
 * @len: (in): 16 byte aligned length of plaintext data.
 *
 * Encrypt plaintext blocks using AES key in CTR mode.
 */
void mega_aes_key_encrypt_ctr(MegaAesKey* aes_key, guchar* from, guchar* to, gsize len)
{
    g_return_if_fail(MEGA_IS_AES_KEY(aes_key));
    g_return_if_fail(from != NULL);
    g_return_if_fail(to != NULL);
    g_return_if_fail(len > 0);

    AES_ctr128_encrypt(from, to, len, &aes_key->priv->enc_key, aes_key->priv->ctr_iv, aes_key->priv->ctr_ecount, &aes_key->priv->ctr_num);
}
Esempio n. 11
0
/**
 * mega_aes_key_generate:
 * @aes_key: a #MegaAesKey
 *
 * Initialize key with random data.
 */
void mega_aes_key_generate(MegaAesKey* aes_key)
{
    guchar rand_key[16];

    g_return_if_fail(MEGA_IS_AES_KEY(aes_key));

    RAND_bytes(rand_key, sizeof(rand_key));

    mega_aes_key_load_binary(aes_key, rand_key);
}
Esempio n. 12
0
/**
 * mega_aes_key_load_enc_ubase64:
 * @aes_key: a #MegaAesKey
 * @data: UBase64 encoded 16 byte AES key data
 * @dec_key: Decryption key
 *
 * Initialize key from #data.
 *
 * Returns: TRUE on success.
 */
gboolean mega_aes_key_load_enc_ubase64(MegaAesKey* aes_key, const gchar* data, MegaAesKey* dec_key)
{
    gsize len;
    guchar* key;

    g_return_val_if_fail(MEGA_IS_AES_KEY(aes_key), FALSE);
    g_return_val_if_fail(data != NULL, FALSE);
    g_return_val_if_fail(MEGA_IS_AES_KEY(dec_key), FALSE);

    key = mega_base64urldecode(data, &len);
    if (key == NULL || len != 16)
    {
        g_free(key);
        return FALSE;
    }

    mega_aes_key_load_enc_binary(aes_key, key, dec_key);

    return TRUE;
}
Esempio n. 13
0
/**
 * mega_aes_key_setup_ctr:
 * @aes_key: a #MegaAesKey
 * @nonce: (element-type guint8) (array fixed-size=8) (transfer none): 8-byte nonce buffer
 * @position: Counter value (block index)
 *
 * Setup CTR mode encryption/decryption.
 */
void mega_aes_key_setup_ctr(MegaAesKey* aes_key, guchar* nonce, guint64 position)
{
    g_return_if_fail(MEGA_IS_AES_KEY(aes_key));
    g_return_if_fail(nonce != NULL);

    memcpy(aes_key->priv->ctr_nonce, nonce, 8);
    aes_key->priv->ctr_position = GUINT64_TO_BE(position);

    memset(aes_key->priv->ctr_ecount, 0, 16);
    aes_key->priv->ctr_num = 0;
}
Esempio n. 14
0
/**
 * mega_filesystem_add_share_key:
 * @filesystem: a #MegaFilesystem
 * @handle: Key handle.
 * @key: AES key.
 *
 * Add key that can be used to decrypt node key.
 */
void mega_filesystem_add_share_key(MegaFilesystem* filesystem, const gchar* handle, MegaAesKey* key)
{
  MegaFilesystemPrivate* priv;

  g_return_if_fail(MEGA_IS_FILESYSTEM(filesystem));
  g_return_if_fail(handle != NULL);
  g_return_if_fail(MEGA_IS_AES_KEY(key));

  priv = filesystem->priv;

  g_hash_table_insert(priv->share_keys, g_strdup(handle), g_object_ref(key));
}
Esempio n. 15
0
/**
 * mega_aes_key_decrypt_raw:
 * @aes_key: a #MegaAesKey
 * @cipher: (element-type guint8) (array length=len): Ciphertext
 * @plain: (element-type guint8) (array length=len) (out caller-allocates): Plaintext output data
 * @len: 16 byte aligned length of ciphertext and plaintext data.
 *
 * Decrypt ciphertext blocks using AES key
 */
void mega_aes_key_decrypt_raw(MegaAesKey* aes_key, const guchar* cipher, guchar* plain, gsize len)
{
    gsize off;

    g_return_if_fail(MEGA_IS_AES_KEY(aes_key));
    g_return_if_fail(cipher != NULL);
    g_return_if_fail(plain != NULL);
    g_return_if_fail(len % 16 == 0);

    for (off = 0; off < len; off += 16)
        AES_decrypt(cipher + off, plain + off, &aes_key->priv->dec_key);
}
Esempio n. 16
0
/**
 * mega_aes_key_load_binary:
 * @aes_key: a #MegaAesKey
 * @data: (element-type guint8) (array fixed-size=16): 16 byte AES key buffer
 *
 * Initialize key from #data.
 */
void mega_aes_key_load_binary(MegaAesKey* aes_key, const guchar* data)
{
    g_return_if_fail(MEGA_IS_AES_KEY(aes_key));
    g_return_if_fail(data != NULL);

    memcpy(aes_key->priv->key, data, 16);

    AES_set_encrypt_key(data, 128, &aes_key->priv->enc_key);
    AES_set_decrypt_key(data, 128, &aes_key->priv->dec_key);

    aes_key->priv->loaded = TRUE;
}
Esempio n. 17
0
/**
 * mega_aes_key_decrypt_cbc_raw:
 * @aes_key: a #MegaAesKey
 * @cipher: (element-type guint8) (array length=len): Ciphertext
 * @plain: (element-type guint8) (array length=len) (out caller-allocates): Plaintext output data
 * @len: 16 byte aligned length of ciphertext and plaintext data.
 *
 * Decrypt ciphertext blocks using AES key in CBC mode with zero IV
 */
void mega_aes_key_decrypt_cbc_raw (MegaAesKey* aes_key, const guchar* cipher, guchar* plain, gsize len)
{
    guchar iv[AES_BLOCK_SIZE] = {0};

    g_return_if_fail(MEGA_IS_AES_KEY(aes_key));
    g_return_if_fail(cipher != NULL);
    g_return_if_fail(plain != NULL);
    g_return_if_fail((len % 16) == 0);
    g_return_if_fail(len > 0);

    AES_cbc_encrypt(cipher, plain, len, &aes_key->priv->dec_key, iv, 0);
}
Esempio n. 18
0
/**
 * mega_aes_key_encrypt:
 * @aes_key: a #MegaAesKey
 * @plain: (in) (element-type guint8) (array length=len): Plaintext input data
 * @len: (in): 16 byte aligned length of plaintext data.
 *
 * Encrypt binary data into ubase64 encoded string.
 *
 * Returns: UBase64 encoded ciphertext.
 */
gchar* mega_aes_key_encrypt(MegaAesKey* aes_key, const guchar* plain, gsize len)
{
    guchar* cipher;
    gchar* str;

    g_return_val_if_fail(MEGA_IS_AES_KEY(aes_key), NULL);
    g_return_val_if_fail(plain != NULL, NULL);
    g_return_val_if_fail((len % 16) == 0, NULL);
    g_return_val_if_fail(len > 0, NULL);

    cipher = g_malloc0(len);
    mega_aes_key_encrypt_raw(aes_key, plain, cipher, len);
    str = mega_base64urlencode(cipher, len);
    g_free(cipher);
    return str;
}
Esempio n. 19
0
/**
 * mega_aes_key_encrypt_cbc:
 * @aes_key: a #MegaAesKey
 * @plain: (in) (element-type guint8) (array length=len): Plaintext input data
 * @len: (in): 16 byte aligned length of plaintext data.
 *
 * Encrypt plaintext blocks using AES key in CBC mode with zero IV into UBase64
 * ciphertext.
 *
 * Returns: UBase64 encoded ciphertext.
 */
gchar* mega_aes_key_encrypt_cbc(MegaAesKey* aes_key, const guchar* plain, gsize len)
{
    guchar* cipher;
    gchar* str;
    guchar iv[AES_BLOCK_SIZE] = {0};

    g_return_val_if_fail(MEGA_IS_AES_KEY(aes_key), NULL);
    g_return_val_if_fail(plain != NULL, NULL);
    g_return_val_if_fail((len % 16) == 0, NULL);
    g_return_val_if_fail(len > 0, NULL);

    cipher = g_malloc0(len);
    AES_cbc_encrypt(plain, cipher, len, &aes_key->priv->enc_key, iv, 1);
    str = mega_base64urlencode(cipher, len);
    g_free(cipher);

    return str;
}
Esempio n. 20
0
/**
 * mega_aes_key_encrypt_string_cbc:
 * @aes_key: a #MegaAesKey
 * @str: Zero terminated string.
 *
 * Zero pad zero terminated string to align data to a AES block size, and
 * encrypt into UBase64 encoded ciphertext.
 *
 * Returns: UBase64 encoded ciphertext.
 */
gchar* mega_aes_key_encrypt_string_cbc(MegaAesKey* aes_key, const gchar* str)
{
    gsize len = 0;
    gchar* plain;
    gchar* cipher;

    g_return_val_if_fail(MEGA_IS_AES_KEY(aes_key), NULL);
    g_return_val_if_fail(str != NULL, NULL);

    // calculate paded size
    len = strlen(str) + 1;
    if (len % 16)
        len += 16 - (len % 16);

    plain = g_malloc0(len);
    memcpy(plain, str, len - 1);
    cipher = mega_aes_key_encrypt_cbc(aes_key, plain, len);
    g_free(plain);

    return cipher;
}
Esempio n. 21
0
void test_aes_construction(void)
{
  MegaAesKey *k, *ek;

  // VALID USES:
  
  // create empty key, check that it is not laoded
  k = mega_aes_key_new();
  g_assert(MEGA_IS_AES_KEY(k));
  g_assert(!mega_aes_key_is_loaded(k));
  g_object_unref(k);

  // create key from UBase64
  k = mega_aes_key_new_from_ubase64(KEY_UBASE64);
  g_assert(MEGA_IS_AES_KEY(k));
  g_assert(mega_aes_key_is_loaded(k));
  g_assert_cmpstr(KEY_UBASE64, ==, mega_aes_key_get_ubase64(k));
  g_object_unref(k);

  // create key from Binary data (use as dec_key below)
  ek = mega_aes_key_new_from_binary(KEY_BINARY);
  g_assert(MEGA_IS_AES_KEY(ek));
  g_assert(mega_aes_key_is_loaded(ek));
  g_assert(memcmp(KEY_BINARY, mega_aes_key_get_binary(ek), 16) == 0);
  g_assert_cmpstr(KEY_UBASE64, ==, mega_aes_key_get_ubase64(ek));

  // create key from encrypted UBase64
  k = mega_aes_key_new_from_enc_ubase64(KEY_UBASE64, ek);
  g_assert(MEGA_IS_AES_KEY(k));
  g_assert(mega_aes_key_is_loaded(k));
  g_assert_cmpstr(KEY_UBASE64, ==, mega_aes_key_get_enc_ubase64(k, ek));
  g_object_unref(k);

  // create key from encrypted Binary data
  k = mega_aes_key_new_from_enc_binary(KEY_BINARY, ek);
  g_assert(MEGA_IS_AES_KEY(k));
  g_assert(mega_aes_key_is_loaded(k));
  g_assert(memcmp(KEY_BINARY, mega_aes_key_get_enc_binary(k, ek), 16) == 0);
  g_object_unref(k);

  g_object_unref(ek);

  // INVALID USES

  k = mega_aes_key_new_from_ubase64(KEY_LONG);
  g_assert(MEGA_IS_AES_KEY(k));
  g_assert(!mega_aes_key_is_loaded(k));
  g_object_unref(k);

  k = mega_aes_key_new_from_ubase64(KEY_SHORT);
  g_assert(MEGA_IS_AES_KEY(k));
  g_assert(!mega_aes_key_is_loaded(k));
  g_object_unref(k);

  k = mega_aes_key_new_from_ubase64(KEY_INVALID);
  g_assert(MEGA_IS_AES_KEY(k));
  g_assert(!mega_aes_key_is_loaded(k));
  g_object_unref(k);

  k = mega_aes_key_new_from_ubase64(KEY_NULL);
  g_assert(MEGA_IS_AES_KEY(k));
  g_assert(!mega_aes_key_is_loaded(k));
  g_object_unref(k);

  g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*data != NULL*");
  k = mega_aes_key_new_from_ubase64(NULL);
  g_test_assert_expected_messages();
  g_assert(MEGA_IS_AES_KEY(k));
  g_assert(!mega_aes_key_is_loaded(k));
  g_object_unref(k);
}
Esempio n. 22
0
/**
 * mega_aes_key_is_loaded:
 * @aes_key: a #MegaAesKey
 *
 * Check if key was successfully loaded. This is useful, when you've created key
 * with #mega_aes_key_new_from_ubase64, and you want to check if it was created
 * correctly.
 *
 * Returns: TRUE if loaded correctly.
 */
gboolean mega_aes_key_is_loaded(MegaAesKey* aes_key)
{
    g_return_val_if_fail(MEGA_IS_AES_KEY(aes_key), FALSE);

    return aes_key->priv->loaded;
}