Descrambling the voice inversion scrambler

Voice inversion is a method of scrambling radio conversations to render speech nearly unintelligible in ordinary radio receivers. As the name implies, it inverts the audio spectrum of a signal, making the lowest frequencies the highest and vice versa. It is not considered encryption; it's merely a sort of Pig Latin on analogue signals. Several voice scramblers utilize it, like the Selectone ST-20.

Update 09/2017: I've later released a simple descrambler tool called deinvert. You should probably try that one instead; these old scripts will be preserved here though.
[Image: A spectrogram of speech, with a cut labeled 'voice inversion' in the middle of the time axis, after which the spectrum appears to be flipped upside down.]

Voice inversion is cancelled by reapplying the inversion, i.e. inverting the audio spectrum again. Here I'll present some least-effort digital descrambling methods for the voice inversion scrambler that may be of interest to hobbyist listeners. The examples are written in Perl.

Easy

In a digitally sampled signal, whole-spectrum inversion can be achieved very easily in the time domain by multiplying every other sample by −1. This is equivalent to amplitude modulating a Nyquist frequency carrier with the signal; the upper sideband will get inverted and nicely overlaid with the lower because of symmetric folding.

Update 09/2017: I've later released a simple descrambler tool called deinvert. You should probably try that one instead; these old scripts will be preserved here though.
my $bandwidth = 4300;

my $fc = $bandwidth * 2;

# Using SoX for resampling and decoding/encoding WAV headers
open my $inf, '-|', 'sox scrambled.wav -r '.$fc.' -c 1 -t .s16 -';
open my $outf, '|-', 'sox -r '.$fc.' -c 1 -t .s16 - descrambled.wav';
my $sign = 1;

while (read $inf, my $sample, 2) {
  # Simply multiply every other sample by -1
  print $outf pack "s", (unpack "s", $sample) * $sign;
  $sign *= -1;
}

Because the whole spectrum is inverted, a sampling rate has to be chosen to (approximately) match the signal bandwidth. Slight distortion will still remain, unless the chosen Nyquist frequency perfectly matches the inverted zero frequency of the signal, or the "inversion carrier" as Selectone calls it. But speech will nevertheless be much more intelligible than in the original scrambled signal.

For example, consider a scrambled piece of audio that seems to have its highest frequency components at 4300 Hz. We would need to resample the audio at a rate of 8600 Hz and multiply every other sample by −1 to get intelligible audio.

To make things simpler, the Selectone ST-20B supports eight discrete carrier frequencies, namely 2632, 2718, 2868, 3023, 3196, 3339, 3495, and 3729 Hz, which they claim to be "the most commonly used inversion formats".

Difficult

If resampling is out of the question, we can also multiply the samples with a sine wave oscillating at the seemingly highest scrambled frequency. This will produce two sidebands; the lower will be our descrambled audio and will be conveniently at baseband. The upper sideband contains the inverted signal, but at such a high frequency it should not significantly impede intelligibility. We could improve the audio further by silencing the upper sideband using a lowpass filter.

# Sample rate
my $fs = 48000;

# Carrier frequency
my $fc = 3729;

# Optional filter - comment out to disable
my $filter = " sinc -$fc";

my $fc = freq($fc, $fs);

# Using SoX for resampling, filtering, encoding/decoding WAV headers
open my $in, '-|', 'sox scrambled.wav -c 1 -b 16 -e signed -t .raw -';
open my $out, '|-', 'sox -r '.$fs.' -c 1 -b 16 -e signed -t .raw - ' .
                    'descrambled.wav' . ($filter // "");

my $phase = 0;
while (read $in, my $sample, 2) {
  $phase += $fc;
  $phase -= 0x10000 if ($phase > 0x7FFF);

  # Multiply signal with sine wave
  print $out pack "s", (unpack "s", $sample) *
                       sin($phase / 0x7FFF * 3.14159);
}

sub freq {
  return int(.5 + $_[0] * 0x10000 / $_[1]);
}

A word about split-band scrambling

Some scramblers, like the PCD4440T, use a split-band inversion where the audio is split into two frequency bands that are then inverted separately and combined. The split frequency is user-adjustable. This is not a significant improvement; it would only require us to do the digital deinversion in two parts with different parameters.

Results

And here's a demo of what it sounds like. We begin with a (fake) scrambled message. Then the easy descramble comes on with a 1000 Hz error in the selected sampling rate; then the easy descramble with an error of 300 Hz; and the difficult method with a spot-on carrier frequency and with the upper sideband also audible. In the end, we also filter out the unwanted upper sideband.

Update 09/2017: I've later released a simple descrambler tool called deinvert. You should probably try that one instead; these old scripts will be preserved here though.

29 comments:

  1. Common cheap Beofeng radios have 16 settings for the scrambler, do they change carrier frequency or do split inversion?

    ReplyDelete
    Replies
    1. The Selectone ST-20 has 8 different carriers to choose from, so I guess that's what they're changing.

      Delete
  2. Spectrum inversion is the ROT13 of the analog world. It is only for polite listeners.

    ReplyDelete
    Replies
    1. It is more useful than that. I own an ols commercial marine radio which only has a USB setting. Voice inversion makes it possible to listen to LSB transmissions. Just shift the frequency about 3 kHz and run the audio tru a voice inverter.

      Delete
  3. Many years ago (in '98) I wrote a program for PC and soundcard to decode scrambled audio with the sine-wave and filtering technique. Unfortunately at the time I didn't knew much about signal theory (I didn't even know of aliasing!) so the result wasn't spectacular.

    The executable is still on the internet:

    http://antoninoporcino.xoom.it/VoiceDescrambler/index.htm

    ReplyDelete
    Replies
    1. Nino,

      I have used your little program many times! I had to play around with the carrier frequency a bit to find the right pitch for the output audio, but it worked well (it actually still works quite nicely), I wish it could hang on to the frequency setting on program close so that I didn't have to re-tune it on start up. But thanks for putting it out for the rest of us to use and enjoy! Maybe someone could do an update for release? ;)
      I've also played around with an SA602 mixer IC with an OSC circuit to handle voice inversion from a hardware angle as well.

      Delete
  4. Just found your blog today (burger puck) and you've got some amazing articles. Loved the one about the modem init tones, I've never seen that old mystery laid out so clearly...

    One thing I discovered with this particular topic is that if you have an SDR application (gnuradio, sdrsharp, etc), you can pass the audio through it and demodulate with LSB. Works in a pinch, especially since you're probably already running the app to pick up the transmissions anyway!

    ReplyDelete
  5. Could you tell me please good spectrum analyzer softwares?

    ReplyDelete
  6. Great post and excellently documented! Well done! I wish you could write another post about split band scrambler decoding.

    ReplyDelete
    Replies
    1. Thanks! I've been pondering that and yes, I may indeed write one.

      Delete
  7. Meny dPMR / NXDN radios uses a 15 bit "spectrum-inversion digital voice scrambling". This mode only works for voice, not text. It's supposed to give the user "sufficient" protection. What is you view on this mode?

    And while 15 bits sounds little, could it be that it makes a brute force attack hard because a human listener needs to hear if the decrypted message makes sense?

    ReplyDelete
    Replies
    1. I think that your assumption about a bruit force is not correct. If you look at the spectrum of the scrambled audio vs normal audio, it should be pretty easy to tell when you have the correct key. This is similar to how normal brute force key guessing works... decrypted stuff doesn't look like random scrambled stuff.

      Delete
  8. Hi. My old speakers (I think they are form 90-s) from time to time capture some scrambled radio conversations. Would you like to take a look at the recording? What does it sound like to you?
    soundcloud.com/int_ua/scrambled

    ReplyDelete
  9. Comment to int_ua
    That sounds like your speakers are picking up a single sideband transmission, with a power line hum causing the "robotic" sound. Because it's acting like a diode detector, the SSB signal is being envelope detected, thus it is losing a considerable amount of intelligibility. I don't think an envelope-detected SSB signal can be reconstituted... but now, watch Oona prove me wrong. :)

    ReplyDelete
  10. I have ben working on the following system for some time I'm no technician just a backyard experimenter. It is a 15-bit digital voice scrambler with a ran of 1 being used on a NXDN 4800 protocol system. That leaves me with 32000 possible variations of scrambled code. Seeing that they use one frequency it seems ridiculous that they now go from digital to digital scrambled as well and it is for roads department maintenance use only? Any thoughts I tried Ninos software for hours with no luck. Thank you in advance

    ReplyDelete
    Replies
    1. Analog voice inversion and NXDN 15 bit digital voice scrambling are two completely different things.

      Try looking for the document "NXDN Technical Specifications TS 1-D version 1.3". It describes how the 15 bit scrambling works.

      Delete
  11. There's been an increase in people using scramblers on UHF CB's where I live. Occasionally I patch an echo repeater in between by tranceivers, and this buffers and replays the transmissions:

    ----------------------------------
    #!/bin/bash
    while true; do
    rec buffer.ogg silence 1 0.1 5% 1 1.0 5%
    DATE=`date +%Y%m%d%H%M%S`
    DPATH=`date +%Y/%m/%d/`
    mkdir -p ./spectro/$DPATH
    mkdir -p ./voice/$DPATH
    echo Renaming buffer file to $DATE
    sox buffer.ogg -n spectrogram -x 300 -y 200 -z 100 -t $DATE.ogg -o ./spectro/$DPATH/$DATE.png
    sox buffer.ogg normbuffer.ogg gain -n -2
    sox normbuffer.ogg -n spectrogram -x 300 -y 200 -z 100 -t $DATE.norm.ogg -o ./spectro/$DPATH/$DATE.norm.png
    mv normbuffer.ogg ./voice/$DPATH/$DATE.ogg
    play pre.ogg ./voice/$DPATH/$DATE.ogg post.ogg
    done
    ----------------------------------------

    Do you know if rec or sox can do the inversion themselves, or do you need to break it out to perl to do it?

    Loving your work! Keep it up!

    ReplyDelete
    Replies
    1. Sox can do a heterodyne mix with --combine multiply. But afaik that can only be done when the length of the file is already known.

      Delete
  12. Just a note, this was used by Motorola cordless telephones ( 49Mhz and 900Mhz ) ~1991-1998. If I remember, it was the only household cordless phone available in the USA that did it at the time. It even had a button to turn off the scrambler at one end of the link so you could hear the scrambled audio (said "Demo" on the button).

    ReplyDelete
  13. Look what wikipedia states https://en.wikipedia.org/wiki/Voice_inversion

    My UHF analogue FM PMR states that it has a 4-code scrambler, but I am not sure which of the two techniques is used, voice inversion or split band voice inversion?

    I am confused of how the wikipedia article is written. Do the carrier frequencies at the end of the article apply to the simple voice inversion as well as the split band voice inversion, or just the one of the two?

    ReplyDelete
  14. Hi,
    I'm usind SDR radio by RTL chipsets. Also SDR#, I have wouxun radios (scrambled voice 8 types) but I could not de-scramble in my pc. Please tell me which software I need to use. Regards.

    ReplyDelete
  15. I'm guessing use Oona Räisänen software found at the GitHub site: https://github.com/windytan/deinvert

    In regards to an even better spectrum analyzer software compared to baudline, I prefer Spectrum Lab v2.90b: http://www.qsl.net/dl4yhf/spectra1.html

    There are way more features for inputs, processing and outputs.

    I have to read up on baudline more, though from my cursory review there didn't seem to be as many options available. I'd have to perform a more compare and contrast list to determine the differences better. However, for the time being I am working on other projects related to sound, mind and body assault detection and RDF like noted on lonestarconsultinginc.com. Thank you for sharing the inversion information since seems really simple once understood. I'm thinking from a SODAR/RADAR perspective that this would be the transmission countermeasure for the internal system or boundary for the assaults detected in the incoming environment transmission (with magnitude and direction). As with most the signals I've detected, they seem to be at a low intensity to blend with the environment amplitude dB. Unfortunately, I am not detecting all the time when the mind and body assaults happen. I really need EEG, ECK, EMG, and other detection on the body to associate the assault signals effect. Thanks again however!

    ReplyDelete
  16. Oona thanks. I make some modifications so it can work in real time with gqrx.

    ReplyDelete
  17. I forgot the link https://github.com/ntoulasd/Descrambler-for-GQRX

    ReplyDelete
  18. I've recently, after much trial and error, managed to get the Perl scripts running and fed some inverted audio to them - but the resulting noise makes it hard to hear anything except the voice peaks, even after modifying the code to use a bandpass filter.
    In the interim I downloaded an old version of Audacity, loaded the audio into that and used the Nyquist prompt with this code : (lowpass8 (mult 2 (highpass8 s 300) (hzosc 3333)) 3100)
    And was able to hear everything, no more noise overpowering the voice.

    ReplyDelete
    Replies
    1. Great solution! I've added a mention of my newer tool 'deinvert' if you still need a tool for that.

      Delete
  19. Windytan, I was experimenting with this using javascript on a wav file that has upper and lower sideband and the non resampling perl code worked perfectly for getting the lower sideband. what would the code look like to recover the upper sideband?

    ReplyDelete

Please browse through the FAQ first, it might be that your question is already answered.

Spammers have even found comments sections, so this comments section is pre-moderated; it will take some time for the comment to show up.