Erlang Client Not Loading NIF


#1

Hi,

Saw this issue posted on a few dated threads…has this been solved? I’m running into the same issue. followed all direction setting Makefile to proper version of Erlang (3.8.2). Currently, I’m running Ubuntu Server (16.04). I’ve apt-get installed the openssl libs. Everything works fine. But when I do the following to test the nif.so file i get the following message:

  1> erlang:load_nif("./aerospike_nif", 0).
        {error,{load_failed,"Failed to load NIF library: './aerospike_nif.so: undefined symbol: RIPEMD160_Init'"}}

I also added the -lcrypto link in the Makefile. Everything compiled nicely no problems but still get the error above.

Any suggestions would be greatly appreciated.

Thank you


#2

So I did a little digging around…and did the following

$ cd /aerospike-client-erlang-2.1.2/
$ grep -Hrl 'RIPEMD160_Init' ./c
$ ./citrusleaf/cf_digest.h
$ cd /c/include/citrusleaf/
$ vim cf_digest.h

/*
 *  Citrusleaf Foundation
 *  include/digest.h - message digests
 *
 *  Copyright 2008 by Citrusleaf.  All rights reserved.
 *  THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE.  THE COPYRIGHT NOTICE
 *  ABOVE DOES NOT EVIDENCE ANY ACTUAL OR INTENDED PUBLICATION.
 */

#pragma once

#include <stddef.h>
#include <stdint.h>
#include <openssl/ripemd.h>

/* SYNOPSIS
 * Cryptographic message digests
 * The intent is to provide an algorithm-neutral API for the computation of
 * cryptographic digests of arbitrary bytes.  Consequently, we define the
 * cf_digest type to be an array of bytes of the appropriate length.
 * The actual computation is done in one shot by calling cf_digest_compute().
 */

#ifdef __cplusplus
extern "C" {
#endif

/* cf_digest
 * Storage for a message digest */
#define CF_DIGEST_KEY_SZ RIPEMD160_DIGEST_LENGTH
typedef struct { uint8_t digest[CF_DIGEST_KEY_SZ]; } cf_digest;

void cf_digest_string(cf_digest *digest, char* output);
void cf_digest_dump(cf_digest *digest);

/* cf_digest_compute
* Compute the digest of an input */
static inline void
cf_digest_compute(void *data, size_t len, cf_digest *d)
{
        RIPEMD160((const unsigned char *) data, len, (unsigned char *) d->digest);
}


// Compute a digest
// the first value is the key data, the second is the set
// DO NOT USE THIS FUNCTION EXTERNALLY
// the externally visible function is 'citrusleaf_calculate_digest', which has
// the proper typing and swizzling

static inline void
cf_digest_compute2(void *data1, size_t len1, void *data2, size_t len2, cf_digest *d)
{
        if (len1 == 0) {
                RIPEMD160((const unsigned char *) data2, len2, (unsigned char *) d->digest);
        }
        else {
                RIPEMD160_CTX c;
                RIPEMD160_Init(&c);
                RIPEMD160_Update(&c, data1, len1);
                RIPEMD160_Update(&c, data2, len2);
                RIPEMD160_Final( (unsigned char *)(d->digest), &c);
        }
}

/* as_partition_getid
 * A brief utility function to derive the partition ID from a digest */

typedef uint16_t cl_partition_id;
static inline cl_partition_id
cl_partition_getid(uint32_t n_partitions, const cf_digest *d)

its this part that stood out to me…

static inline void
cf_digest_compute2(void *data1, size_t len1, void *data2, size_t len2, cf_digest *d)
{
        if (len1 == 0) {
                RIPEMD160((const unsigned char *) data2, len2, (unsigned char *) d->digest);
        }
        else {
                RIPEMD160_CTX c;
                RIPEMD160_Init(&c);
                RIPEMD160_Update(&c, data1, len1);
                RIPEMD160_Update(&c, data2, len2);
                RIPEMD160_Final( (unsigned char *)(d->digest), &c);
        }
}

According to openssl.org

The following functions may be used if the message is not completely stored in memory:

RIPEMD160_Init() initializes a RIPEMD160_CTX structure.

RIPEMD160_Update() can be called repeatedly with chunks of the message to be hashed (len bytes at data).

RIPEMD160_Final() places the message digest in md, which must have space for RIPEMD160_DIGEST_LENGTH == 20 bytes of output, and erases the RIPEMD160_CTX.

Applications should use the higher level functions EVP_DigestInit etc. instead of calling the hash functions directly.

From what I can tell it is directly calling the hash functions RIPEMD160_Init instead of using EVP_DigestInit as recommended. Also on openssl.org RIPEMD160_Init is defined as type int but the code doesn’t explicitly define type int. I don’t know if this is also causing the problem.

I don’t know C all that well. But I hope this can provide some clues about the cause of the problem. I really wanna start using Aerospike in my dev setup.

Any guidance will be appreciated…


#3

The same functionality is used in the aerospike_client_c, which supports all ubuntu platforms. Most likely this is still some library path resolution or version issue with the Erlang installation.

Incidentally, the Aerospike Erlang client is not actively worked on due to the limited number of users, and thus missing many of the new features that Aerospike server has developed (such as secondary indexing, geo query, list/maps)

See http://www.aerospike.com/docs/guide/client_matrix.html for most up-to-date functionality support.


#4

Thank you,

Are you suggesting I try the aerospike_client_c for my Ubuntu 16.04 install?

And yes, I can already see there isn’t that much support for it… Riak_TS might be a better option.


#5

Not much support for Riak these days either.

If someone who knows Erlang better ( great tip about EVP_DigestInit ) would love to dive in, we’re happy to help along getting Erlang into a proper community support role.