[sip-comm-dev] GSoC 09 - OTR - First term results (DSA Signature sign/verify using BC/libgcrypt)


#1

Hello all,

According to FIPS-186-3/p. DSA Signature Generation, (r,s) should be
generated as follows:

*Let N be the bit length of q. Let min(N, outlen) denote the minimum of the
positive integers N and outlen, where outlen is the bit length of the hash
function output block. The signature of a message M consists of the pair of
numbers r and s that is computed according to the following equations:

r = (g^k mod p) mod q.
z = the leftmost min(N, outlen) bits of Hash(M).
s = (k^-1 (z + xr)) mod q.

* BouncyCastle has method
org.bouncycastle.crypto.signers.DSASigner.class:calculateE that calculates z
and then calculates s.

libgcrypt on the other hand seems to directly calculate s from M.

If this is the case, I think this is a bug in libgcrypt, can anyone confirm
this?

···

On Mon, Jul 13, 2009 at 4:27 AM, Geekius Caesar <geekius.caesar@gmail.com>wrote:

Hello Werner,

Thank you for your reply, I have modified the code based on your
suggestions. The problem now is that the calculated v is not equal with r
(libgcrypt-1.4.1/cipher/dsa.c:380) so verification fails again.

I use a custom build libgcrypt-1.4.1 and I have inserted the following
calls in libgcrypt-1.4.1/cipher/dsa.c:verify

log_mpidump (" r:", r);
log_mpidump (" s:", s);
log_mpidump (" hash:", hash);
log_mpidump (" q:" , pkey->q);
log_mpidump (" p:" , pkey->p);
log_mpidump (" g:" , pkey->g);
log_mpidump (" y:" , pkey->y);

I do the same in otr4j (
http://code.google.com/p/otr4j/source/browse/src/net/java/otr4j/StateMachine.java#787
)

This way I can verify r in otr4j/bc is the same as r in libotr/libgcrypt, s
in otr4j/bc is the same as s in libotr/libgcrypt, e.t.c.

I will insert more logging calls in libgcrypt/bouncycastle to see why
exactly the resulting v is not equal with r.

kind regards,
George.

On Sun, Jul 12, 2009 at 2:48 PM, Werner Dittmann < > Werner.Dittmann@t-online.de> wrote:

Goerge,

Geekius Caesar schrieb:

<SNIP --- SNAP>

>
> I did not proceed into creating transformation sets for the rest of the
> protocols because there is an issue that the DSA signature does not
verify
> in Pidgin/libotr, this action is taken in the OTR Protocol Draft, High
Level
> Overview, Authenticated Key Exchange, Step 9. I tried to sign using
> BouncyCastle Leightweight API instead of the Standard JCE, but that
failed
> too.
>
> To make sure the signature I use is correct, I created a set of test
cases
> to verify signatures created with bouncycastle using the Sun JCE
provider
> and visa versa, but that failed too.

As per specification and an according cross-check of libotr implementation
IMHO you cannot use the JCE DSA variant to sign. The JCE variant _always_
hashes the data, then signs it. The OTR specification reads like this:

sigA(MA) (SIG)
   This is the signature, using the private part of the key pubA, of the
   32-byte MA (which does not need to be hashed again to produce the
   signature).

IMHO "which does not need to be hashed" is a bit ambigous and should read
"must not be hased". The libotr implementation also reflects this (see
code
snippet below). Each signature value (r and s) is copied into a 20 byte
field,
padded with zero if r or s are shorter than 20 bytes. This padding is not
explictily stated in the spec (it should be stated however).

IMHO you need to rebuild the specific DSA signature mode using the
appropriate BC functions (SHA256 HMAC, DSA) to be compliant to the spec
and
libotr. As said, the JCE methods cannot be used because of their
"embedded"
hash mechanism.

Here the function from libotr that performs the signature (inline comments
added by me):

/* Sign data using a private key. The data must be small enough to be
* signed (i.e. already hashed, if necessary). The signature will be
* returned in *sigp, which the caller must free(). Its length will be
* returned in *siglenp. */

gcry_error_t otrl_privkey_sign(unsigned char **sigp, size_t *siglenp,
       OtrlPrivKey *privkey, const unsigned char *data, size_t len)
{
   gcry_mpi_t r,s, datampi;
   gcry_sexp_t dsas, rs, ss, sigs, datas;
   size_t nr, ns;
   const enum gcry_mpi_format format = GCRYMPI_FMT_USG; //wd: raw int
format

   if (privkey->pubkey_type != OTRL_PUBKEY_TYPE_DSA)
       return gcry_error(GPG_ERR_INV_VALUE);

   *sigp = malloc(40); //wd: get signature storage
   if (sigp == NULL) return gcry_error(GPG_ERR_ENOMEM);
   *siglenp = 40;

   if (len) { //wd: transform raw data into a gcrypt
multi-precision int
       gcry_mpi_scan(&datampi, GCRYMPI_FMT_USG, data, len, NULL);
   } else {
       datampi = gcry_mpi_set_ui(NULL, 0);
   }
   gcry_sexp_build(&datas, NULL, "(%m)", datampi); //wd: build
s-expression that holds data now
   gcry_mpi_release(datampi);
   gcry_pk_sign(&sigs, datas, privkey->privkey); //wd: sign the s-expr,
return a s-expr in sigs
   gcry_sexp_release(datas);
   dsas = gcry_sexp_find_token(sigs, "dsa", 0); //wd: get "dsa" sub
s-expr (contains r and s)
   gcry_sexp_release(sigs);
   rs = gcry_sexp_find_token(dsas, "r", 0); //wd: get r s-expr
   ss = gcry_sexp_find_token(dsas, "s", 0); //wd: get s s-expr
   gcry_sexp_release(dsas);
   r = gcry_sexp_nth_mpi(rs, 1, GCRYMPI_FMT_USG); //wd: get r MPI
   gcry_sexp_release(rs);
   s = gcry_sexp_nth_mpi(ss, 1, GCRYMPI_FMT_USG); //wd: get s MPI
   gcry_sexp_release(ss);
   gcry_mpi_print(format, NULL, 0, &nr, r); //wd: dummy print just
to get lentth in "nr"
   gcry_mpi_print(format, NULL, 0, &ns, s); //wd: dummy print just
to get length in "ns"
   memset(*sigp, 0, 40); //wd: fill with zero
to assure zero padding
   gcry_mpi_print(format, (*sigp)+(20-nr), nr, NULL, r); //wd: extract
data from MPI into signature buffer
   gcry_mpi_print(format, (*sigp)+20+(20-ns), ns, NULL, s); //wd: with
length as computed above
   gcry_mpi_release(r);
   gcry_mpi_release(s);

   return gcry_error(GPG_ERR_NO_ERROR);
}

Verification is just the reversed way :slight_smile: .

Regards,
Werner

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#2

libgcrypt verifies the signature in cipher/dsa.c:verify.

To test my hypothesis, if I modified BouncyCastle as to not use calculateE,
and signature verification worked fine between SIP Communicator/otr4j/BC +
Pidgin/libotr/libgcrypt.

Still I would like a confirmation. Also if this is indeed the case we may
have to generate/verify signatures without BouncyCastle, but within otr4j
using the buggy process, at least until libgcrypt fixes the problem and the
change has been incorporated in major linux distributions.

···

On Tue, Jul 14, 2009 at 3:16 PM, Geekius Caesar <geekius.caesar@gmail.com>wrote:

Hello all,

According to FIPS-186-3/p. DSA Signature Generation, (r,s) should be
generated as follows:

*Let N be the bit length of q. Let min(N, outlen) denote the minimum of
the positive integers N and outlen, where outlen is the bit length of the
hash function output block. The signature of a message M consists of the
pair of numbers r and s that is computed according to the following
equations:

r = (g^k mod p) mod q.
z = the leftmost min(N, outlen) bits of Hash(M).
s = (k^-1 (z + xr)) mod q.

* BouncyCastle has method
org.bouncycastle.crypto.signers.DSASigner.class:calculateE that calculates z
and then calculates s.

libgcrypt on the other hand seems to directly calculate s from M.

If this is the case, I think this is a bug in libgcrypt, can anyone confirm
this?

On Mon, Jul 13, 2009 at 4:27 AM, Geekius Caesar <geekius.caesar@gmail.com>wrote:

Hello Werner,

Thank you for your reply, I have modified the code based on your
suggestions. The problem now is that the calculated v is not equal with r
(libgcrypt-1.4.1/cipher/dsa.c:380) so verification fails again.

I use a custom build libgcrypt-1.4.1 and I have inserted the following
calls in libgcrypt-1.4.1/cipher/dsa.c:verify

log_mpidump (" r:", r);
log_mpidump (" s:", s);
log_mpidump (" hash:", hash);
log_mpidump (" q:" , pkey->q);
log_mpidump (" p:" , pkey->p);
log_mpidump (" g:" , pkey->g);
log_mpidump (" y:" , pkey->y);

I do the same in otr4j (
http://code.google.com/p/otr4j/source/browse/src/net/java/otr4j/StateMachine.java#787
)

This way I can verify r in otr4j/bc is the same as r in libotr/libgcrypt,
s in otr4j/bc is the same as s in libotr/libgcrypt, e.t.c.

I will insert more logging calls in libgcrypt/bouncycastle to see why
exactly the resulting v is not equal with r.

kind regards,
George.

On Sun, Jul 12, 2009 at 2:48 PM, Werner Dittmann < >> Werner.Dittmann@t-online.de> wrote:

Goerge,

Geekius Caesar schrieb:

<SNIP --- SNAP>

>
> I did not proceed into creating transformation sets for the rest of the
> protocols because there is an issue that the DSA signature does not
verify
> in Pidgin/libotr, this action is taken in the OTR Protocol Draft, High
Level
> Overview, Authenticated Key Exchange, Step 9. I tried to sign using
> BouncyCastle Leightweight API instead of the Standard JCE, but that
failed
> too.
>
> To make sure the signature I use is correct, I created a set of test
cases
> to verify signatures created with bouncycastle using the Sun JCE
provider
> and visa versa, but that failed too.

As per specification and an according cross-check of libotr
implementation
IMHO you cannot use the JCE DSA variant to sign. The JCE variant _always_
hashes the data, then signs it. The OTR specification reads like this:

sigA(MA) (SIG)
   This is the signature, using the private part of the key pubA, of the
   32-byte MA (which does not need to be hashed again to produce the
   signature).

IMHO "which does not need to be hashed" is a bit ambigous and should read
"must not be hased". The libotr implementation also reflects this (see
code
snippet below). Each signature value (r and s) is copied into a 20 byte
field,
padded with zero if r or s are shorter than 20 bytes. This padding is not
explictily stated in the spec (it should be stated however).

IMHO you need to rebuild the specific DSA signature mode using the
appropriate BC functions (SHA256 HMAC, DSA) to be compliant to the spec
and
libotr. As said, the JCE methods cannot be used because of their
"embedded"
hash mechanism.

Here the function from libotr that performs the signature (inline
comments
added by me):

/* Sign data using a private key. The data must be small enough to be
* signed (i.e. already hashed, if necessary). The signature will be
* returned in *sigp, which the caller must free(). Its length will be
* returned in *siglenp. */

gcry_error_t otrl_privkey_sign(unsigned char **sigp, size_t *siglenp,
       OtrlPrivKey *privkey, const unsigned char *data, size_t len)
{
   gcry_mpi_t r,s, datampi;
   gcry_sexp_t dsas, rs, ss, sigs, datas;
   size_t nr, ns;
   const enum gcry_mpi_format format = GCRYMPI_FMT_USG; //wd: raw int
format

   if (privkey->pubkey_type != OTRL_PUBKEY_TYPE_DSA)
       return gcry_error(GPG_ERR_INV_VALUE);

   *sigp = malloc(40); //wd: get signature storage
   if (sigp == NULL) return gcry_error(GPG_ERR_ENOMEM);
   *siglenp = 40;

   if (len) { //wd: transform raw data into a gcrypt
multi-precision int
       gcry_mpi_scan(&datampi, GCRYMPI_FMT_USG, data, len, NULL);
   } else {
       datampi = gcry_mpi_set_ui(NULL, 0);
   }
   gcry_sexp_build(&datas, NULL, "(%m)", datampi); //wd: build
s-expression that holds data now
   gcry_mpi_release(datampi);
   gcry_pk_sign(&sigs, datas, privkey->privkey); //wd: sign the
s-expr, return a s-expr in sigs
   gcry_sexp_release(datas);
   dsas = gcry_sexp_find_token(sigs, "dsa", 0); //wd: get "dsa" sub
s-expr (contains r and s)
   gcry_sexp_release(sigs);
   rs = gcry_sexp_find_token(dsas, "r", 0); //wd: get r s-expr
   ss = gcry_sexp_find_token(dsas, "s", 0); //wd: get s s-expr
   gcry_sexp_release(dsas);
   r = gcry_sexp_nth_mpi(rs, 1, GCRYMPI_FMT_USG); //wd: get r MPI
   gcry_sexp_release(rs);
   s = gcry_sexp_nth_mpi(ss, 1, GCRYMPI_FMT_USG); //wd: get s MPI
   gcry_sexp_release(ss);
   gcry_mpi_print(format, NULL, 0, &nr, r); //wd: dummy print
just to get lentth in "nr"
   gcry_mpi_print(format, NULL, 0, &ns, s); //wd: dummy print
just to get length in "ns"
   memset(*sigp, 0, 40); //wd: fill with zero
to assure zero padding
   gcry_mpi_print(format, (*sigp)+(20-nr), nr, NULL, r); //wd: extract
data from MPI into signature buffer
   gcry_mpi_print(format, (*sigp)+20+(20-ns), ns, NULL, s); //wd: with
length as computed above
   gcry_mpi_release(r);
   gcry_mpi_release(s);

   return gcry_error(GPG_ERR_NO_ERROR);
}

Verification is just the reversed way :slight_smile: .

Regards,
Werner

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#3

Goerge,

I'll take care of this. The author of libgcrypt is Werner Koch that I know
personally and I'm also subscribed to the libgcrypt list. To inform Werner
Koch I summarize your findings (you've done a great job here) and see what
he says to this issue.

As for the time being I agree with you to perform the sign/verify "manually"
and not using BC. I assume you have copied and modified the BC functions?
Can you upload the modifications to the otr4j source repository? Then I can
update mine here as well and we can work on the "modified very lightweigth
BC" library.

I'll keep you informed.

Regards,
Werner

Geekius Caesar schrieb:

···

libgcrypt verifies the signature in cipher/dsa.c:verify.

To test my hypothesis, if I modified BouncyCastle as to not use calculateE,
and signature verification worked fine between SIP Communicator/otr4j/BC +
Pidgin/libotr/libgcrypt.

Still I would like a confirmation. Also if this is indeed the case we may
have to generate/verify signatures without BouncyCastle, but within otr4j
using the buggy process, at least until libgcrypt fixes the problem and the
change has been incorporated in major linux distributions.

On Tue, Jul 14, 2009 at 3:16 PM, Geekius Caesar <geekius.caesar@gmail.com>wrote:

Hello all,

According to FIPS-186-3/p. DSA Signature Generation, (r,s) should be
generated as follows:

*Let N be the bit length of q. Let min(N, outlen) denote the minimum of
the positive integers N and outlen, where outlen is the bit length of the
hash function output block. The signature of a message M consists of the
pair of numbers r and s that is computed according to the following
equations:

r = (g^k mod p) mod q.
z = the leftmost min(N, outlen) bits of Hash(M).
s = (k^-1 (z + xr)) mod q.

* BouncyCastle has method
org.bouncycastle.crypto.signers.DSASigner.class:calculateE that calculates z
and then calculates s.

libgcrypt on the other hand seems to directly calculate s from M.

If this is the case, I think this is a bug in libgcrypt, can anyone confirm
this?

On Mon, Jul 13, 2009 at 4:27 AM, Geekius Caesar <geekius.caesar@gmail.com>wrote:

Hello Werner,

Thank you for your reply, I have modified the code based on your
suggestions. The problem now is that the calculated v is not equal with r
(libgcrypt-1.4.1/cipher/dsa.c:380) so verification fails again.

I use a custom build libgcrypt-1.4.1 and I have inserted the following
calls in libgcrypt-1.4.1/cipher/dsa.c:verify

log_mpidump (" r:", r);
log_mpidump (" s:", s);
log_mpidump (" hash:", hash);
log_mpidump (" q:" , pkey->q);
log_mpidump (" p:" , pkey->p);
log_mpidump (" g:" , pkey->g);
log_mpidump (" y:" , pkey->y);

I do the same in otr4j (
http://code.google.com/p/otr4j/source/browse/src/net/java/otr4j/StateMachine.java#787
)

This way I can verify r in otr4j/bc is the same as r in libotr/libgcrypt,
s in otr4j/bc is the same as s in libotr/libgcrypt, e.t.c.

I will insert more logging calls in libgcrypt/bouncycastle to see why
exactly the resulting v is not equal with r.

kind regards,
George.

On Sun, Jul 12, 2009 at 2:48 PM, Werner Dittmann < >>> Werner.Dittmann@t-online.de> wrote:

Goerge,

Geekius Caesar schrieb:

<SNIP --- SNAP>

I did not proceed into creating transformation sets for the rest of the
protocols because there is an issue that the DSA signature does not

verify

in Pidgin/libotr, this action is taken in the OTR Protocol Draft, High

Level

Overview, Authenticated Key Exchange, Step 9. I tried to sign using
BouncyCastle Leightweight API instead of the Standard JCE, but that

failed

too.

To make sure the signature I use is correct, I created a set of test

cases

to verify signatures created with bouncycastle using the Sun JCE

provider

and visa versa, but that failed too.

As per specification and an according cross-check of libotr
implementation
IMHO you cannot use the JCE DSA variant to sign. The JCE variant _always_
hashes the data, then signs it. The OTR specification reads like this:

sigA(MA) (SIG)
   This is the signature, using the private part of the key pubA, of the
   32-byte MA (which does not need to be hashed again to produce the
   signature).

IMHO "which does not need to be hashed" is a bit ambigous and should read
"must not be hased". The libotr implementation also reflects this (see
code
snippet below). Each signature value (r and s) is copied into a 20 byte
field,
padded with zero if r or s are shorter than 20 bytes. This padding is not
explictily stated in the spec (it should be stated however).

IMHO you need to rebuild the specific DSA signature mode using the
appropriate BC functions (SHA256 HMAC, DSA) to be compliant to the spec
and
libotr. As said, the JCE methods cannot be used because of their
"embedded"
hash mechanism.

Here the function from libotr that performs the signature (inline
comments
added by me):

/* Sign data using a private key. The data must be small enough to be
* signed (i.e. already hashed, if necessary). The signature will be
* returned in *sigp, which the caller must free(). Its length will be
* returned in *siglenp. */

gcry_error_t otrl_privkey_sign(unsigned char **sigp, size_t *siglenp,
       OtrlPrivKey *privkey, const unsigned char *data, size_t len)
{
   gcry_mpi_t r,s, datampi;
   gcry_sexp_t dsas, rs, ss, sigs, datas;
   size_t nr, ns;
   const enum gcry_mpi_format format = GCRYMPI_FMT_USG; //wd: raw int
format

   if (privkey->pubkey_type != OTRL_PUBKEY_TYPE_DSA)
       return gcry_error(GPG_ERR_INV_VALUE);

   *sigp = malloc(40); //wd: get signature storage
   if (sigp == NULL) return gcry_error(GPG_ERR_ENOMEM);
   *siglenp = 40;

   if (len) { //wd: transform raw data into a gcrypt
multi-precision int
       gcry_mpi_scan(&datampi, GCRYMPI_FMT_USG, data, len, NULL);
   } else {
       datampi = gcry_mpi_set_ui(NULL, 0);
   }
   gcry_sexp_build(&datas, NULL, "(%m)", datampi); //wd: build
s-expression that holds data now
   gcry_mpi_release(datampi);
   gcry_pk_sign(&sigs, datas, privkey->privkey); //wd: sign the
s-expr, return a s-expr in sigs
   gcry_sexp_release(datas);
   dsas = gcry_sexp_find_token(sigs, "dsa", 0); //wd: get "dsa" sub
s-expr (contains r and s)
   gcry_sexp_release(sigs);
   rs = gcry_sexp_find_token(dsas, "r", 0); //wd: get r s-expr
   ss = gcry_sexp_find_token(dsas, "s", 0); //wd: get s s-expr
   gcry_sexp_release(dsas);
   r = gcry_sexp_nth_mpi(rs, 1, GCRYMPI_FMT_USG); //wd: get r MPI
   gcry_sexp_release(rs);
   s = gcry_sexp_nth_mpi(ss, 1, GCRYMPI_FMT_USG); //wd: get s MPI
   gcry_sexp_release(ss);
   gcry_mpi_print(format, NULL, 0, &nr, r); //wd: dummy print
just to get lentth in "nr"
   gcry_mpi_print(format, NULL, 0, &ns, s); //wd: dummy print
just to get length in "ns"
   memset(*sigp, 0, 40); //wd: fill with zero
to assure zero padding
   gcry_mpi_print(format, (*sigp)+(20-nr), nr, NULL, r); //wd: extract
data from MPI into signature buffer
   gcry_mpi_print(format, (*sigp)+20+(20-ns), ns, NULL, s); //wd: with
length as computed above
   gcry_mpi_release(r);
   gcry_mpi_release(s);

   return gcry_error(GPG_ERR_NO_ERROR);
}

Verification is just the reversed way :slight_smile: .

Regards,
Werner

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#4

Hello Werner,

Thank you for taking care of the libgcrypt issue. As you assumed, I copied
the entire DSASigner class and renamed it in BuggyDSASigner.

I have uploaded the latest otr4j in it's repository, and I have updated SIP
Communicator repository as well and now a basic session can be established.
For the time being, you need to start it (the session) from Pidgin and some
other things are missing but I will fix them.

Here's what otr4j currently uses as far as bouncycastle is concerned:

import org.bouncycastle.crypto.*;
import org.bouncycastle.crypto.generators.*;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.util.*;
import org.bouncycastle.util.encoders.*;

kind regards,
George.

···

On Tue, Jul 14, 2009 at 8:27 PM, Werner Dittmann < Werner.Dittmann@t-online.de> wrote:

Goerge,

I'll take care of this. The author of libgcrypt is Werner Koch that I know
personally and I'm also subscribed to the libgcrypt list. To inform Werner
Koch I summarize your findings (you've done a great job here) and see what
he says to this issue.

As for the time being I agree with you to perform the sign/verify
"manually"
and not using BC. I assume you have copied and modified the BC functions?
Can you upload the modifications to the otr4j source repository? Then I can
update mine here as well and we can work on the "modified very lightweigth
BC" library.

I'll keep you informed.

Regards,
Werner

Geekius Caesar schrieb:
> libgcrypt verifies the signature in cipher/dsa.c:verify.
>
> To test my hypothesis, if I modified BouncyCastle as to not use
calculateE,
> and signature verification worked fine between SIP Communicator/otr4j/BC
+
> Pidgin/libotr/libgcrypt.
>
> Still I would like a confirmation. Also if this is indeed the case we may
> have to generate/verify signatures without BouncyCastle, but within otr4j
> using the buggy process, at least until libgcrypt fixes the problem and
the
> change has been incorporated in major linux distributions.
>
> On Tue, Jul 14, 2009 at 3:16 PM, Geekius Caesar < > geekius.caesar@gmail.com>wrote:
>
>> Hello all,
>>
>> According to FIPS-186-3/p. DSA Signature Generation, (r,s) should be
>> generated as follows:
>>
>> *Let N be the bit length of q. Let min(N, outlen) denote the minimum of
>> the positive integers N and outlen, where outlen is the bit length of
the
>> hash function output block. The signature of a message M consists of the
>> pair of numbers r and s that is computed according to the following
>> equations:
>>
>> r = (g^k mod p) mod q.
>> z = the leftmost min(N, outlen) bits of Hash(M).
>> s = (k^-1 (z + xr)) mod q.
>>
>> * BouncyCastle has method
>> org.bouncycastle.crypto.signers.DSASigner.class:calculateE that
calculates z
>> and then calculates s.
>>
>> libgcrypt on the other hand seems to directly calculate s from M.
>>
>> If this is the case, I think this is a bug in libgcrypt, can anyone
confirm
>> this?
>>
>> On Mon, Jul 13, 2009 at 4:27 AM, Geekius Caesar < > geekius.caesar@gmail.com>wrote:
>>
>>> Hello Werner,
>>>
>>> Thank you for your reply, I have modified the code based on your
>>> suggestions. The problem now is that the calculated v is not equal with
r
>>> (libgcrypt-1.4.1/cipher/dsa.c:380) so verification fails again.
>>>
>>> I use a custom build libgcrypt-1.4.1 and I have inserted the following
>>> calls in libgcrypt-1.4.1/cipher/dsa.c:verify
>>>
>>> log_mpidump (" r:", r);
>>> log_mpidump (" s:", s);
>>> log_mpidump (" hash:", hash);
>>> log_mpidump (" q:" , pkey->q);
>>> log_mpidump (" p:" , pkey->p);
>>> log_mpidump (" g:" , pkey->g);
>>> log_mpidump (" y:" , pkey->y);
>>>
>>> I do the same in otr4j (
>>>
http://code.google.com/p/otr4j/source/browse/src/net/java/otr4j/StateMachine.java#787
>>> )
>>>
>>> This way I can verify r in otr4j/bc is the same as r in
libotr/libgcrypt,
>>> s in otr4j/bc is the same as s in libotr/libgcrypt, e.t.c.
>>>
>>> I will insert more logging calls in libgcrypt/bouncycastle to see why
>>> exactly the resulting v is not equal with r.
>>>
>>> kind regards,
>>> George.
>>>
>>>
>>> On Sun, Jul 12, 2009 at 2:48 PM, Werner Dittmann < > >>> Werner.Dittmann@t-online.de> wrote:
>>>
>>>> Goerge,
>>>>
>>>>
>>>> Geekius Caesar schrieb:
>>>>
>>>> <SNIP --- SNAP>
>>>>
>>>>> I did not proceed into creating transformation sets for the rest of
the
>>>>> protocols because there is an issue that the DSA signature does not
>>>> verify
>>>>> in Pidgin/libotr, this action is taken in the OTR Protocol Draft,
High
>>>> Level
>>>>> Overview, Authenticated Key Exchange, Step 9. I tried to sign using
>>>>> BouncyCastle Leightweight API instead of the Standard JCE, but that
>>>> failed
>>>>> too.
>>>>>
>>>>> To make sure the signature I use is correct, I created a set of test
>>>> cases
>>>>> to verify signatures created with bouncycastle using the Sun JCE
>>>> provider
>>>>> and visa versa, but that failed too.
>>>> As per specification and an according cross-check of libotr
>>>> implementation
>>>> IMHO you cannot use the JCE DSA variant to sign. The JCE variant
_always_
>>>> hashes the data, then signs it. The OTR specification reads like this:
>>>>
>>>> sigA(MA) (SIG)
>>>> This is the signature, using the private part of the key pubA, of
the
>>>> 32-byte MA (which does not need to be hashed again to produce the
>>>> signature).
>>>>
>>>> IMHO "which does not need to be hashed" is a bit ambigous and should
read
>>>> "must not be hased". The libotr implementation also reflects this (see
>>>> code
>>>> snippet below). Each signature value (r and s) is copied into a 20
byte
>>>> field,
>>>> padded with zero if r or s are shorter than 20 bytes. This padding is
not
>>>> explictily stated in the spec (it should be stated however).
>>>>
>>>> IMHO you need to rebuild the specific DSA signature mode using the
>>>> appropriate BC functions (SHA256 HMAC, DSA) to be compliant to the
spec
>>>> and
>>>> libotr. As said, the JCE methods cannot be used because of their
>>>> "embedded"
>>>> hash mechanism.
>>>>
>>>> Here the function from libotr that performs the signature (inline
>>>> comments
>>>> added by me):
>>>>
>>>>
>>>> /* Sign data using a private key. The data must be small enough to be
>>>> * signed (i.e. already hashed, if necessary). The signature will be
>>>> * returned in *sigp, which the caller must free(). Its length will
be
>>>> * returned in *siglenp. */
>>>>
>>>> gcry_error_t otrl_privkey_sign(unsigned char **sigp, size_t *siglenp,
>>>> OtrlPrivKey *privkey, const unsigned char *data, size_t len)
>>>> {
>>>> gcry_mpi_t r,s, datampi;
>>>> gcry_sexp_t dsas, rs, ss, sigs, datas;
>>>> size_t nr, ns;
>>>> const enum gcry_mpi_format format = GCRYMPI_FMT_USG; //wd: raw int
>>>> format
>>>>
>>>> if (privkey->pubkey_type != OTRL_PUBKEY_TYPE_DSA)
>>>> return gcry_error(GPG_ERR_INV_VALUE);
>>>>
>>>> *sigp = malloc(40); //wd: get signature storage
>>>> if (sigp == NULL) return gcry_error(GPG_ERR_ENOMEM);
>>>> *siglenp = 40;
>>>>
>>>> if (len) { //wd: transform raw data into a gcrypt
>>>> multi-precision int
>>>> gcry_mpi_scan(&datampi, GCRYMPI_FMT_USG, data, len, NULL);
>>>> } else {
>>>> datampi = gcry_mpi_set_ui(NULL, 0);
>>>> }
>>>> gcry_sexp_build(&datas, NULL, "(%m)", datampi); //wd: build
>>>> s-expression that holds data now
>>>> gcry_mpi_release(datampi);
>>>> gcry_pk_sign(&sigs, datas, privkey->privkey); //wd: sign the
>>>> s-expr, return a s-expr in sigs
>>>> gcry_sexp_release(datas);
>>>> dsas = gcry_sexp_find_token(sigs, "dsa", 0); //wd: get "dsa"
sub
>>>> s-expr (contains r and s)
>>>> gcry_sexp_release(sigs);
>>>> rs = gcry_sexp_find_token(dsas, "r", 0); //wd: get r s-expr
>>>> ss = gcry_sexp_find_token(dsas, "s", 0); //wd: get s s-expr
>>>> gcry_sexp_release(dsas);
>>>> r = gcry_sexp_nth_mpi(rs, 1, GCRYMPI_FMT_USG); //wd: get r MPI
>>>> gcry_sexp_release(rs);
>>>> s = gcry_sexp_nth_mpi(ss, 1, GCRYMPI_FMT_USG); //wd: get s MPI
>>>> gcry_sexp_release(ss);
>>>> gcry_mpi_print(format, NULL, 0, &nr, r); //wd: dummy print
>>>> just to get lentth in "nr"
>>>> gcry_mpi_print(format, NULL, 0, &ns, s); //wd: dummy print
>>>> just to get length in "ns"
>>>> memset(*sigp, 0, 40); //wd: fill with
zero
>>>> to assure zero padding
>>>> gcry_mpi_print(format, (*sigp)+(20-nr), nr, NULL, r); //wd: extract
>>>> data from MPI into signature buffer
>>>> gcry_mpi_print(format, (*sigp)+20+(20-ns), ns, NULL, s); //wd: with
>>>> length as computed above
>>>> gcry_mpi_release(r);
>>>> gcry_mpi_release(s);
>>>>
>>>> return gcry_error(GPG_ERR_NO_ERROR);
>>>> }
>>>>
>>>> Verification is just the reversed way :slight_smile: .
>>>>
>>>> Regards,
>>>> Werner
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
>>>> For additional commands, e-mail:
dev-help@sip-communicator.dev.java.net
>>>>
>>>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#5

Hey folks,

Geekius Caesar wrote:

Hello Werner,

Thank you for taking care of the libgcrypt issue. As you assumed, I
copied the entire DSASigner class and renamed it in BuggyDSASigner.

Is there a reliable way for us to detect what implementation our
interlocutor is using so that we could determine which DSA signer (i.e.
standard or Buggy)to use?

Cheers
Emil

···

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#6

Hello Emil,

For the verification part, we could try to verify against both cases (buggy
and standard) and require at least one to succeed. (I'm not sure if this is
the right thing to do though).

For the signing part I can see two cases. If we are the first who receive a
signature for verification (i.e. we receive a reveal signature message and
after that we are supposed to reply a signature message), based on which
verification process succeeded (buggy or standard) we can discover which
algorithm the other party is using, if not we can only guess what kind of
signature the other party is expecting.

To summarize, we may be able to successfully verify a valid signature that
was generated either way (not sure if this leaves security issues), but I
can not see a way to be 100% sure our signature will be successfully
verified.

If this is indeed a bug, we can wait and see how libotr will tackle the
issue once libgcrypt fixes the supposed bug.

kind regards,
George.

···

On Wed, Jul 15, 2009 at 2:20 PM, Emil Ivov <emcho@sip-communicator.org>wrote:

Hey folks,

Geekius Caesar wrote:
> Hello Werner,
>
> Thank you for taking care of the libgcrypt issue. As you assumed, I
> copied the entire DSASigner class and renamed it in BuggyDSASigner.

Is there a reliable way for us to detect what implementation our
interlocutor is using so that we could determine which DSA signer (i.e.
standard or Buggy)to use?

Cheers
Emil

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#7

George, Emil,

the BC DSA signature algorithm implements the latest standard according
to FIP-186-3. This standard is _very_ new (approved in 2009) and only this
standard allows hashes other than SHA-1.

Thus the implementation in libgcrypt is not buggy but adheres to FIPS-186-1,
186-2. As a matter of fact, it's the OTR implementation that "misused" DSA
because it uses an SHA256 HMAC as input even for DSA implementations
according to FIPS-186-2 ;-).

AFAIK OTR uses DSA domain parameters that generate a 1024bit p (L) and a
160bit q (N) to sign the output of a 256 HMAC. This is not according to
FIPS-186-3 that states:

<quote>
It is recommended that the security strength of the (L, N) pair and the security strength of the
hash function used for the generation of digital signatures be the same unless an agreement has
been made between participating entities to use a stronger hash function. When the length of the
output of the hash function is greater than N (i.e., the bit length of q), then the leftmost N bits of
the hash function output block shall be used in any calculation using the hash function output
during the generation or verification of a digital signature. A hash function that provides a lower
security strength than the (L, N) pair ordinarily should not be used, since this would reduce the
security strength of the digital signature process to a level no greater than that provided by the
hash function.
</quote>

As for SC: currently the libotr uses this and I would recomend to be "bug"
compliant and generate "buggy" signature when otr4j cannot detect which type to
use. Because otr4j knows about this problem it can deal with this during
verification (receiver makes it right). Using this way interop with libotr
works.

BTW, is there any way during the previous messages to detect which otr
implementation is used by the other party? ZRTP for example provides this
information during the Hello handshake (protocol version number of implementation
info of the ZRTP protocol implementation). If this is possible then we
could insert a SC identification and select the right way to do DSA.

Regards,
Werner

Geekius Caesar schrieb:

···

Hello Emil,

For the verification part, we could try to verify against both cases (buggy
and standard) and require at least one to succeed. (I'm not sure if this is
the right thing to do though).

For the signing part I can see two cases. If we are the first who receive a
signature for verification (i.e. we receive a reveal signature message and
after that we are supposed to reply a signature message), based on which
verification process succeeded (buggy or standard) we can discover which
algorithm the other party is using, if not we can only guess what kind of
signature the other party is expecting.

To summarize, we may be able to successfully verify a valid signature that
was generated either way (not sure if this leaves security issues), but I
can not see a way to be 100% sure our signature will be successfully
verified.

If this is indeed a bug, we can wait and see how libotr will tackle the
issue once libgcrypt fixes the supposed bug.

kind regards,
George.

On Wed, Jul 15, 2009 at 2:20 PM, Emil Ivov <emcho@sip-communicator.org>wrote:

Hey folks,

Geekius Caesar wrote:

Hello Werner,

Thank you for taking care of the libgcrypt issue. As you assumed, I
copied the entire DSASigner class and renamed it in BuggyDSASigner.

Is there a reliable way for us to detect what implementation our
interlocutor is using so that we could determine which DSA signer (i.e.
standard or Buggy)to use?

Cheers
Emil

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#8

Hello Werner,

Thank you for clearing things up. It was too hard to believe that a buggy
DSA signature generation/verification algorithm existed in a so
popular/essential library such as libgcrypt -shame on me for not taking a
look in older specifications-. This seems to lead into an "interoperability
hell", maybe signers should be further parametrized to support operation
modes per FIPS, but that is out of the scope of this discussion and not our
problem :slight_smile:

As for OTR implementation discovery, OTR protocol does not define a way that
allows that (OTR implementation discovery) during the Authenticated Key
Exchange (this is the part where we need it).

A non-standard *extension *to the OTR protocol that would allow OTR
implementation discovery would be to define one more whitespace tag + a
unique query message that only otr4j would understand it's special meaning
but still remain compatible with standard OTR whitespace tags and query
messages, but I want to finish with the library and start building the SC
UI, so I would like to stick with the "buggy" signature for now if that's OK
with you.

kind regards,
George

···

On Wed, Jul 15, 2009 at 4:39 PM, Werner Dittmann < Werner.Dittmann@t-online.de> wrote:

George, Emil,

the BC DSA signature algorithm implements the latest standard according
to FIP-186-3. This standard is _very_ new (approved in 2009) and only this
standard allows hashes other than SHA-1.

Thus the implementation in libgcrypt is not buggy but adheres to
FIPS-186-1,
186-2. As a matter of fact, it's the OTR implementation that "misused" DSA
because it uses an SHA256 HMAC as input even for DSA implementations
according to FIPS-186-2 ;-).

AFAIK OTR uses DSA domain parameters that generate a 1024bit p (L) and a
160bit q (N) to sign the output of a 256 HMAC. This is not according to
FIPS-186-3 that states:

<quote>
It is recommended that the security strength of the (L, N) pair and the
security strength of the
hash function used for the generation of digital signatures be the same
unless an agreement has
been made between participating entities to use a stronger hash function.
When the length of the
output of the hash function is greater than N (i.e., the bit length of q),
then the leftmost N bits of
the hash function output block shall be used in any calculation using the
hash function output
during the generation or verification of a digital signature. A hash
function that provides a lower
security strength than the (L, N) pair ordinarily should not be used, since
this would reduce the
security strength of the digital signature process to a level no greater
than that provided by the
hash function.
</quote>

As for SC: currently the libotr uses this and I would recomend to be "bug"
compliant and generate "buggy" signature when otr4j cannot detect which
type to
use. Because otr4j knows about this problem it can deal with this during
verification (receiver makes it right). Using this way interop with libotr
works.

BTW, is there any way during the previous messages to detect which otr
implementation is used by the other party? ZRTP for example provides this
information during the Hello handshake (protocol version number of
implementation
info of the ZRTP protocol implementation). If this is possible then we
could insert a SC identification and select the right way to do DSA.

Regards,
Werner

Geekius Caesar schrieb:
> Hello Emil,
>
> For the verification part, we could try to verify against both cases
(buggy
> and standard) and require at least one to succeed. (I'm not sure if this
is
> the right thing to do though).
>
> For the signing part I can see two cases. If we are the first who receive
a
> signature for verification (i.e. we receive a reveal signature message
and
> after that we are supposed to reply a signature message), based on which
> verification process succeeded (buggy or standard) we can discover which
> algorithm the other party is using, if not we can only guess what kind of
> signature the other party is expecting.
>
> To summarize, we may be able to successfully verify a valid signature
that
> was generated either way (not sure if this leaves security issues), but I
> can not see a way to be 100% sure our signature will be successfully
> verified.
>
> If this is indeed a bug, we can wait and see how libotr will tackle the
> issue once libgcrypt fixes the supposed bug.
>
> kind regards,
> George.
>
> On Wed, Jul 15, 2009 at 2:20 PM, Emil Ivov <emcho@sip-communicator.org > >wrote:
>
>> Hey folks,
>>
>> Geekius Caesar wrote:
>>> Hello Werner,
>>>
>>> Thank you for taking care of the libgcrypt issue. As you assumed, I
>>> copied the entire DSASigner class and renamed it in BuggyDSASigner.
>> Is there a reliable way for us to detect what implementation our
>> interlocutor is using so that we could determine which DSA signer (i.e.
>> standard or Buggy)to use?
>>
>> Cheers
>> Emil
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
>> For additional commands, e-mail: dev-help@sip-communicator.dev.java.net
>>
>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#9

Hi George,

Geekius Caesar schrieb:

Hello Werner,

Thank you for clearing things up. It was too hard to believe that a buggy
DSA signature generation/verification algorithm existed in a so
popular/essential library such as libgcrypt -shame on me for not taking a
look in older specifications-. This seems to lead into an "interoperability
hell", maybe signers should be further parametrized to support operation
modes per FIPS, but that is out of the scope of this discussion and not our
problem :slight_smile:

As for OTR implementation discovery, OTR protocol does not define a way that
allows that (OTR implementation discovery) during the Authenticated Key
Exchange (this is the part where we need it).

A non-standard *extension *to the OTR protocol that would allow OTR
implementation discovery would be to define one more whitespace tag + a
unique query message that only otr4j would understand it's special meaning
but still remain compatible with standard OTR whitespace tags and query
messages, but I want to finish with the library and start building the SC
UI, so I would like to stick with the "buggy" signature for now if that's OK
with you.

absolutely ok. Just go on with this and complete alle necessary functions
of the lib and the integration into SC.

I have an idea how to solve the signature issue, just need to do some
tests how to generate a DSA keypair that has a key strength of
L=2048, N=256. If N=256 then the bit length of q is also 256 and this
is then the same length as the SAH256HMAC and its not truncated. For
verification we probably need to stay with the "double-verify" method.

Regards,
Werner

kind regards,
George

George, Emil,

the BC DSA signature algorithm implements the latest standard according
to FIP-186-3. This standard is _very_ new (approved in 2009) and only this
standard allows hashes other than SHA-1.

Thus the implementation in libgcrypt is not buggy but adheres to
FIPS-186-1,
186-2. As a matter of fact, it's the OTR implementation that "misused" DSA
because it uses an SHA256 HMAC as input even for DSA implementations
according to FIPS-186-2 ;-).

AFAIK OTR uses DSA domain parameters that generate a 1024bit p (L) and a
160bit q (N) to sign the output of a 256 HMAC. This is not according to
FIPS-186-3 that states:

<quote>
It is recommended that the security strength of the (L, N) pair and the
security strength of the
hash function used for the generation of digital signatures be the same
unless an agreement has
been made between participating entities to use a stronger hash function.
When the length of the
output of the hash function is greater than N (i.e., the bit length of q),
then the leftmost N bits of
the hash function output block shall be used in any calculation using the
hash function output
during the generation or verification of a digital signature. A hash
function that provides a lower
security strength than the (L, N) pair ordinarily should not be used, since
this would reduce the
security strength of the digital signature process to a level no greater
than that provided by the
hash function.
</quote>

As for SC: currently the libotr uses this and I would recomend to be "bug"
compliant and generate "buggy" signature when otr4j cannot detect which
type to
use. Because otr4j knows about this problem it can deal with this during
verification (receiver makes it right). Using this way interop with libotr
works.

BTW, is there any way during the previous messages to detect which otr
implementation is used by the other party? ZRTP for example provides this
information during the Hello handshake (protocol version number of
implementation
info of the ZRTP protocol implementation). If this is possible then we
could insert a SC identification and select the right way to do DSA.

Regards,
Werner

<SNIP --- SNAP>

···

On Wed, Jul 15, 2009 at 4:39 PM, Werner Dittmann < > Werner.Dittmann@t-online.de> wrote:

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#10

George,

unfortunately BC cannot generate the required key pairs. Thus BC
implemented FIPS-186-3 with respect to the signature but not with
respect generate key pairs suitable for hash sizes greater than
160 bits. Thus the idea mentioned does not work out :frowning: .

Regards,
Werner

Werner Dittmann schrieb:

···

Hi George,

Geekius Caesar schrieb:

Hello Werner,

Thank you for clearing things up. It was too hard to believe that a buggy
DSA signature generation/verification algorithm existed in a so
popular/essential library such as libgcrypt -shame on me for not taking a
look in older specifications-. This seems to lead into an "interoperability
hell", maybe signers should be further parametrized to support operation
modes per FIPS, but that is out of the scope of this discussion and not our
problem :slight_smile:

As for OTR implementation discovery, OTR protocol does not define a way that
allows that (OTR implementation discovery) during the Authenticated Key
Exchange (this is the part where we need it).

A non-standard *extension *to the OTR protocol that would allow OTR
implementation discovery would be to define one more whitespace tag + a
unique query message that only otr4j would understand it's special meaning
but still remain compatible with standard OTR whitespace tags and query
messages, but I want to finish with the library and start building the SC
UI, so I would like to stick with the "buggy" signature for now if that's OK
with you.

absolutely ok. Just go on with this and complete alle necessary functions
of the lib and the integration into SC.

I have an idea how to solve the signature issue, just need to do some
tests how to generate a DSA keypair that has a key strength of
L=2048, N=256. If N=256 then the bit length of q is also 256 and this
is then the same length as the SAH256HMAC and its not truncated. For
verification we probably need to stay with the "double-verify" method.

Regards,
Werner

kind regards,
George

On Wed, Jul 15, 2009 at 4:39 PM, Werner Dittmann < >> Werner.Dittmann@t-online.de> wrote:

George, Emil,

the BC DSA signature algorithm implements the latest standard according
to FIP-186-3. This standard is _very_ new (approved in 2009) and only this
standard allows hashes other than SHA-1.

Thus the implementation in libgcrypt is not buggy but adheres to
FIPS-186-1,
186-2. As a matter of fact, it's the OTR implementation that "misused" DSA
because it uses an SHA256 HMAC as input even for DSA implementations
according to FIPS-186-2 ;-).

AFAIK OTR uses DSA domain parameters that generate a 1024bit p (L) and a
160bit q (N) to sign the output of a 256 HMAC. This is not according to
FIPS-186-3 that states:

<quote>
It is recommended that the security strength of the (L, N) pair and the
security strength of the
hash function used for the generation of digital signatures be the same
unless an agreement has
been made between participating entities to use a stronger hash function.
When the length of the
output of the hash function is greater than N (i.e., the bit length of q),
then the leftmost N bits of
the hash function output block shall be used in any calculation using the
hash function output
during the generation or verification of a digital signature. A hash
function that provides a lower
security strength than the (L, N) pair ordinarily should not be used, since
this would reduce the
security strength of the digital signature process to a level no greater
than that provided by the
hash function.
</quote>

As for SC: currently the libotr uses this and I would recomend to be "bug"
compliant and generate "buggy" signature when otr4j cannot detect which
type to
use. Because otr4j knows about this problem it can deal with this during
verification (receiver makes it right). Using this way interop with libotr
works.

BTW, is there any way during the previous messages to detect which otr
implementation is used by the other party? ZRTP for example provides this
information during the Hello handshake (protocol version number of
implementation
info of the ZRTP protocol implementation). If this is possible then we
could insert a SC identification and select the right way to do DSA.

Regards,
Werner

<SNIP --- SNAP>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net