3

I'm working with a server that requires that part of the login URL include authentification. The way this scheme works (as recommended in the manuals) is that

  • a public / private key pair is generated using Java JDK keytool (which creates them in a Java keystore)
  • a certificate is generated for the key pair using Java JDK keytool
  • the certificate is installed on the server.

When logging on the client (my code)

  • generates a plaintext token string
  • signs the plaintext token string with the private key using SHA1 and DSA
  • includes the signed token string in the login URL.

The Java keytool does not provide a mechanism to export the private key from the keystore, but separately I have Java code to extract the private key from the keystore and save it in a file - based on How do I list / export private keys from a keystore?.

This all works when the client uses Java to do the signing, with code like the following.

String plaintext = "This is a sample plaintext token string";
Signature instance = Signature.getInstance("SHA1withDSA");
instance.initSign(privateKey);
instance.update((plaintext).getBytes());
byte[] signature = instance.sign();

It also works when the client uses PHP to do the signing, with code like the following. Here the private key is retrieved from the Java keystore file in PHP.]

$privateKey = openssl_pkey_get_private("file://$keyfile", $keystorePassword);
openssl_sign($paramsEncoded, $signature, $privateKey, OPENSSL_ALGO_DSS1))

However I now have a situation where a customer wants to construct the login URL using a Bash script and openssl - and that does not work. My most current version of that code looks like the following, which does a SHA1 message digest and then a DSA sign. But the server rejects the token.

echo $tokenString | openssl dgst -sha1 > tokendigest
openssl dgst -dss1 -passin pass:$storePassword -sign $privateKeyFile > tokensigned

I came across this post (Using SHA1 and RSA with java.security.Signature vs. MessageDigest and Cipher) which suggests that the Java Signature sign method doesn't sign the digest, but rather signs the concatenation of the digest algorithm ID and the digest. After stepping through the code in the post it appears that (for SHA1) the digest needs to be prefixed with the bytes 48 33 48 9 6 5 43 14 3 2 26 5 0 4 20. But even after adding that I still can't get opensll to produce a signed token that is acceptable to the server.

Does anyone know how to use openssl to emulate the Java Signature sign method?

Community
  • 1
  • 1
Torid
  • 4,176
  • 1
  • 28
  • 29

1 Answers1

2

The other post is a red herring. DSA works differently than RSA and does not use the MessageDigest-prefix.

But the openssl dgst -dss1 should work directly (it includes the SHA1 digesting).

Have you tried this?

echo -n $tokenString |
  openssl dgst -dss1 -passin pass:$storePassword -sign $privateKeyFile > tokensigned
Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
Rasmus Faber
  • 48,631
  • 24
  • 141
  • 189
  • I just tried that with the same "Error in token login" results. I even added an openssl verify (as below) - where openssl reported Verified OK. `echo $tokenString | openssl dgst -dss1 -passin pass:$storePassword -sign $privateKeyFile > $signedTokenOpensslFile echo $tokenString | openssl dgst -dss1 -verify $publicKeyFile -signature $signedTokenOpensslFile` – Torid Apr 13 '12 at 17:58
  • @Torid: Your problem might be the extra new-line that `echo` adds to the string. Try `echo -n`. – Rasmus Faber Apr 13 '12 at 18:33
  • Yes. The `echo -n` fixed it. I love stackoverflow.com - even when it makes me feel slightly stupid. Thanks! – Torid Apr 13 '12 at 19:05