I'm not an encryption guru, but the obvious question is: can I use One Time Pad encryption? Then you can simply incorporate a large block of truly random bits into your decoding system and use random data to convert decimal digits in a reversible way.
If this is acceptable, we just need to figure out how the decoder knows where in the random block to look for a key to decode any particular message. If you can send a plaintext timestamp using encrypted text, then it’s easy: convert the timestamp to a number, say, the number of seconds from the date of an era, a module that is listed by the length of the random block, and you have an offset within the block.
With a sufficiently large block of randomness, this should be irreparable. You could encrypt random bits with strong encryption, so the user must enter a long password to unlock the decoder; thus, even if decryption software were hijacked, it would still not be easy to crash the system.
If you have an interest in this, and I would like for me to expand further, let me know. I do not want to spend a lot of time on an answer that does not meet your needs.
EDIT: Good, with a tiny bit of support (“you can be on something”). I am expanding my answer.
The idea is that you get a block of randomness. One easy way to do this is to simply extract data from Linux /dev/random . Now I'm going to assume that we have a way to find the index in this randomness block for each message.
Index into a random block and pull out ten bytes of data. Each byte is a number from 0 to 255. Add each of these numbers to the corresponding digit from the plaintext, modulo 10, and you have the numbers of the ciphertext. You can easily reverse this if you have a random data block and an index: you get random bits and subtract them from the encryption digits modulo 10.
You can think of it as placing numbers from 0 to 9 in a ring. Adding is counting clockwise around the ring, and subtracting is counterclockwise. You can add or subtract any number, and it will work. (My original version of this answer suggested using only 3 bits per digit. Not enough, as @Baffe Boyois below. Thanks for this correction.)
If a simple text digit is 6 and a random number is 117, then: 6 + 117 == 123, modulo 10 == 3. 3 - 117 == -114, modulo 10 == 6.
As I said, the problem of finding the index is simple if you can use external plaintext information such as a timestamp. Even if your opponent knows that you are using a timestamp to help decode messages, it does nothing good without a random block.
The index search problem is also simple if the message is always delivered; you can have a consistent index generation system and say, "This is the fourth message I received, so I use the fourth index in the series." As a trivial example, if this is the fourth message received, you can agree to use the index value 16 (4 for the fourth message, 4 bytes per one-time notepad). But you can also use numbers from an approved pseudo-random number generator, initialized with a consistent constant value as a seed, and then you get a somewhat unpredictable series of indices in a random block.
Depending on your needs, you may have a really large chunk of random data (hundreds of megabytes or even more). If you use 10 bytes as a one-time pad and never use overlapping pads or re-pads, then 1 megabyte of random data will produce more than 100,000 one-time pads.