jansolo / aXbo-research

Open source version of the client software package for the aXbo Sleep Phase Alarm Clock.
http://www.axbo.com
MIT License
17 stars 0 forks source link

Generating SoundPackage (AXS file) #1

Open Jerberus opened 11 years ago

Jerberus commented 11 years ago

When attempting to create an AXS file, need methods and example for using Crypto wrap functions / license file / etc. to be able to generate and encrypt soundPackages that can be uploaded to the AXBO. Can successfully extract from an AXBO axs file and get unencrypted files, but not successfully build an AXS to upload to the AXBO.

jansolo commented 11 years ago

The bad news is that you currently can not create a sound package, because you are missing the required private key. The good news is, that the encryption for the sound packages will be removed in the near future, so everyone can load sounds to aXbo. There is already a tool, that we use to create sound packages, but unfortunately it is not in a state to be released yet. Eventually I plan to integrate sound package creation into aXbo research. The utility methods to load, create and write sound packages can already be found in the com.dreikraft.axbo.sound.SoundPackageUtil class

neverpanic commented 6 years ago

You can put your own sounds into a sound package by grabbing an official package, grabbing the public key from this source tree (src/resources/sounds.pub.rsa), extracting license.key from the sound package (it's a ZIP file) and running

openssl rsautl \
  -decrypt \
  -pubin sounds.pub.rsa \
  -in license.key \
  -out aeskey

Then, extract the rest of the ZIP file. The files can be decrypted using

openssl aes-128-ecb \
  -in "package-info.xml" \
  -out "decrypted/package-info.xml" \
  -d \
  -K "$(xxd -ps aeskey)"

Then, you can modify the XML and sound files at will. I successfully converted a file into a format playable by my aXbo using

ffmpeg \
  -i "inputfile" \
  -ac 1 \
  -ar 11025 \
  -codec:a pcm_mulaw \
  "outputfile.wav"

Next, you will have to re-encrypt the files. You can use the inverse operation of the decryption by replacing the -d switch with -e. Then, assemble the encrypted files into a ZIP archive, reusing the same license.key file that you originally extracted. aXbo research will load your sound file and flash it to your aXbo.

All of this works because the only thing protected by the RSA crypto is the AES key, but there is no signature or any other integrity protection on the files. Of course the entire crypto is moot anyway, since you could just re-implement the serial protocol to flash custom sound files to your aXbo (but this is arguably easier).

soulsrevenge commented 5 years ago

@neverpanic I tried your method, and can't get through. I'm using openssl for windows (see GnuWin32 bundle) and tried executing the mentionned commands, but it fails if I don't add the option -inkey (-pubin doesn't seem to allow parameters).

With it,the command line becomes :

openssl.exe rsautl -decrypt -pubin -inkey "sounds.pub.rsa" -in "license.key" -out "aeskey"

But then, the output is "A private key is needed for this operation"

It would seem a logical conclusion, since following the encryption logic a public key allows encrypting but a private key would always be required to decrypt, at least as far as my knowledge allows me.

Maybe I'm missing something critical here ? In any case my only issue is I don't seem to be able to extract the aes key, maybe you could upload it somewhere for us to use ?

neverpanic commented 5 years ago

@neverpanic I tried your method, and can't get through. I'm using openssl for windows (see GnuWin32 bundle) and tried executing the mentionned commands, but it fails if I don't add the option -inkey (-pubin doesn't seem to allow parameters).

With it,the command line becomes :

openssl.exe rsautl -decrypt -pubin -inkey "sounds.pub.rsa" -in "license.key" -out "aeskey"

But then, the output is "A private key is needed for this operation"

You're right. I'm reasonably sure that I've actually tried this back when I wrote this, but it no longer works for me either.

It would seem a logical conclusion, since following the encryption logic a public key allows encrypting but a private key would always be required to decrypt, at least as far as my knowledge allows me.

There's really no difference between an RSA private and an RSA public key, other than that one is kept private and the other is not. Consequently, there's no reason an RSA private key cannot be used for encryption. However, it's a very uncommon – and nonsensical – use-case; why would you encrypt something that can be decrypted by everybody (since it uses the public key for decryption).

Nonetheless, that seems to be what the aXbo people have done in this case. OpenSSL should be able to do this and used to be in previous versions, but they seem to have added a safeguard against this misuse (probably for the better).

There's a couple of solutions that can be used to get around this:

(a): Exploit the fact that encryption and decryption are the same operation (but with different keys) in RSA. Consequently, if we encrypt the license.key file with the public key, that's effectively decrypting the file, too. Unfortunately padding and all other sorts of issues cause this to be problematic, but if we just use the raw primitives, it still works:

openssl rsautl \
  -encrypt \
  -pubin \
  -keyform DER \
  -inkey sounds.pub.rsa \
  -raw \
  -in license.key | xxd -ps

You'll get 0001 followed by a bunch of ffs ending in 00 and then the AES key in hex. You can directly use that hex representation where I used $(xxd -ps aeskey) above.

(b) Use the same bits of Java code used by aXbo to decrypt the AES key.

The code for this is

import java.io.*;
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;

public class UnwrapKey {
    public static byte[] readFile(final String fileName)
            throws FileNotFoundException, IOException {
        byte[] buf = new byte[1024];
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(fileName));
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        int available = 0;
        while ((available = in.read(buf)) != -1) {
            out.write(buf, 0, available);
        }

        return out.toByteArray();
    }

    public static Key getPublicRsaKey(final String fileName)
            throws FileNotFoundException, IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(new X509EncodedKeySpec(readFile(fileName)));
    }

    public static Key unwrapKey(final String inFile, final String keyFile)
            throws FileNotFoundException, IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException {
        Cipher rsaCipher = Cipher.getInstance("RSA");
        rsaCipher.init(Cipher.UNWRAP_MODE, getPublicRsaKey(keyFile));
        byte[] in = readFile(inFile);
        return rsaCipher.unwrap(in, "AES", Cipher.SECRET_KEY);
    }   

    public static void main(String[] args)
            throws FileNotFoundException, IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException {
        Key key = unwrapKey(args[0], args[1]);
        byte[] keyBytes = key.getEncoded();
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(args[2]));
        System.out.println("Writing " + keyBytes.length + " bytes to " + args[2]);
        out.write(keyBytes, 0, keyBytes.length);
        out.close();
    }
}

Store in a file called UnwrapKey.java, compile with javac UnwrapKey.java, run as java UnwrapKey license.key sounds.pub.rsa output. The output file will contain the raw AES key.

Maybe I'm missing something critical here ? In any case my only issue is I don't seem to be able to extract the aes key, maybe you could upload it somewhere for us to use ?

I'm not sure what the legal implications of publishing somebody else's crypto key are in my jurisdiction. I know the crypto isn't effective anyway, but I don't want to have to explain this to a judge. For this reason, I'd rather not publish the key directly.

soulsrevenge commented 5 years ago

@neverpanic Thank you very much for taking of your time to write such a clear and detailed answer.

Your first hack worked perfectly, and I even ended writing two short scripts to decrypt/reencrypt a file or a whole folder (see attachments). The rest was very simple, since regarding the sounds anything in the format you decribed will play fine.

I didn't know the RSA encryption was that flawed,but in this precise case it's for the better.

I'm not sure what the legal implications of publishing somebody else's crypto key are in my jurisdiction. I know the crypto isn't effective anyway, but I don't want to have to explain this to a judge. For this reason, I'd rather not publish the key directly.

I dindn't really think about it, eager as I was to find a solution, but I must admit you're right on this.

And now, if anyone wants to crack the key....method's up there !

PS: files with .sh extension don't work so I renamed them to .txt extract.txt encrypt.txt

neverpanic commented 5 years ago

@neverpanic Thank you very much for taking of your time to write such a clear and detailed answer.

Your first hack worked perfectly, and I even ended writing two short scripts to decrypt/reencrypt a file or a whole folder (see attachments). The rest was very simple, since regarding the sounds anything in the format you decribed will play fine.

Glad it worked for you!

I didn't know the RSA encryption was that flawed,but in this precise case it's for the better.

Just to be clear on this, there's no flaw in RSA there – that's just how the math works. Its the use in aXbo that's flawed.

jansolo commented 5 years ago

@neverpanic You can simply remove the encryption completely from the aXbo-research implementation, because the clock itself does not use encryption nor license keys, but only the correctly encoded and structured sound files. Take a look into SoundPackageUtil.java. It should be much easier to removce the encryption/decryption stuff of the sound package files, than the encrypt/decrypt the files manually.

jansolo commented 5 years ago

I had a little bit spare time to look into sources. Hopefully I will be able to remove the encryption logic from aXbo research this week (at least in a branch).

However, it's a very uncommon – and nonsensical – use-case; why would you encrypt something that can be decrypted by everybody (since it uses the public key for decryption).

@neverpanic The idea was not to prevent somebody to decrypt sound packages, but to prevent creating custom sound packages and load them onto aXbo, as we initially planned to sell additional sound packages. We never followed this plan, so the encryption code is obsolete.

Igor836boec commented 2 years ago

Hello, could you help me with the script, please?