def getstegresult(stegcollection, cipher, key, aesmode, verbose): # Decodes an entire series of steg messages, or notifies you if you have # some steg messages but are awaiting more transmissions to decode if cipher == "none": return True, "", True, jts.deciphersteg( stegcollection, cipher, key, aesmode, verbose, False) # Steg has already been unprepped else: localarray = stegcollection[0] if verbose: print "localarray : " + str(localarray) localarray = jts.jt65tobytes(localarray) if getstatusbyte(localarray) & 0x80 != 0x80: # The first packet in the collection does not represet a 'start' # packet, reset the collection and catch the next one return False, "Monitored steg mid-transmission, resetting for next transmission.", True, "" # The first packet represents a 'start' packet, do we have all the # packets? expectedpackets = getstatusbyte(localarray) & 0x7F if expectedpackets <= len(stegcollection): return True, "", True, jts.deciphersteg(stegcollection, cipher, key, aesmode, verbose, False) # The multi-packet transmission is not complete yet return False, "(" + str(len(stegcollection)) + "/" + str( expectedpackets) + ") total packets received.", False, ""
def test_NoCipher_WithSteg_Extra(self): for i in range(MAX_COVER_NOISE): # Encode with more JT65 msgs than necessary jt65msgs = [ "KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44", "KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44" ] jt65data = jts.jt65encodemessages(jt65msgs, False) stegmsg = "BEACON FTW AND DEF CON 22" key = ''.join( random.choice(string.ascii_letters + string.digits) for n in xrange(random.randint(10, 30))) hidekey = jts.getnoisekey(key) cipherdata = jts.createciphermsgs(len(jt65data), stegmsg, "none", "", "", "", False) finalmsgs = jts.steginject(jt65data, i, cipherdata, hidekey, False) # Decode finalresultmsgs = list(finalmsgs) stegdata = jts.retrievesteg(finalmsgs, hidekey, False) resultstegmsg = jts.deciphersteg(stegdata, "none", "", "", False) decodedjt65msgs = jts.decodemessages(finalmsgs, False) self.assertEqual(len(decodedjt65msgs), len(jt65msgs)) for i in range(len(jt65msgs)): self.assertEqual(jt65msgs[i].rstrip(), decodedjt65msgs[i].rstrip()) self.assertEqual(stegmsg.rstrip(), resultstegmsg.rstrip())
def test_AES_CFB(self): for i in range(MAX_COVER_NOISE): # Encode jt65msgs = [ "KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44", "KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44" ] jt65data = jts.jt65encodemessages(jt65msgs, False) stegmsg = "DEF CON 22" key = ''.join( random.choice(string.ascii_letters + string.digits) for n in xrange(random.randint(10, 30))) hidekey = jts.getnoisekey(key) cipherdata = jts.createciphermsgs( len(jt65data), stegmsg, "AES", "AES is totes secure, right? Yeah", "", "CFB", False) finalmsgs = jts.steginject(jt65data, i, cipherdata, hidekey, False) # Decode finalresultmsgs = list(finalmsgs) stegdata = jts.retrievesteg(finalmsgs, hidekey, False) resultstegmsg = jts.deciphersteg( stegdata, "AES", "AES is totes secure, right? Yeah", "CFB", False) decodedjt65msgs = jts.decodemessages(finalmsgs, False) self.assertEqual(len(decodedjt65msgs), len(jt65msgs)) for i in range(len(jt65msgs)): self.assertEqual(jt65msgs[i].rstrip(), decodedjt65msgs[i].rstrip()) self.assertEqual(stegmsg.rstrip(), resultstegmsg.rstrip())
def test_NoCipher_WithSteg_WAV(self): for i in range(MAX_COVER_NOISE): # Encode jt65msgs = ["KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44"] jt65data = jts.jt65encodemessages(jt65msgs, False) stegmsg = "BEACON FTW AND DEF CON 22" key = ''.join(random.choice(string.ascii_letters + string.digits) for n in xrange(random.randint(10, 30))) hidekey = jts.getnoisekey(key) cipherdata = jts.createciphermsgs( len(jt65data), stegmsg, "none", "", "", "", False) finalmsgs = jts.steginject(jt65data, i, cipherdata, hidekey, False) for index, value in enumerate(finalmsgs): tones = jt65sound.toneswithsync(value) jt65sound.outputwavfile( "test_output-00" + str(index) + ".wav", tones) # Decode result1 = jt65sound.inputwavfile("test_output-000.wav") result2 = jt65sound.inputwavfile("test_output-001.wav") symbols1, confidence1, wavmsg1, s2db, freq, a1, a2 = result1[0] symbols2, confidence2, wavmsg2, s2db, freq, a1, a2 = result2[0] os.remove("test_output-000.wav") os.remove("test_output-001.wav") finalresultmsgs = [symbols1, symbols2] stegdata = jts.retrievesteg(finalresultmsgs, hidekey, False) resultstegmsg = jts.deciphersteg(stegdata, "none", "", "", False) decodedjt65msgs = jts.decodemessages(finalresultmsgs, False) self.assertEqual(len(result1), 1) self.assertEqual(len(result2), 1) self.assertEqual(len(decodedjt65msgs), len(jt65msgs)) for i in range(len(jt65msgs)): self.assertEqual( jt65msgs[i].rstrip(), decodedjt65msgs[i].rstrip()) self.assertEqual(stegmsg.rstrip(), resultstegmsg.rstrip())
def test_OTP_Extra(self): for i in range(MAX_COVER_NOISE): # Encode with more JT65 msgs than necessary jt65msgs = [ "KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44", "KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44", "KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44"] jt65data = jts.jt65encodemessages(jt65msgs, False) stegmsg = "BEACON FTW AND DEF CON 22" key = ''.join(random.choice(string.ascii_letters + string.digits) for n in xrange(random.randint(10, 30))) hidekey = jts.getnoisekey(key) cipherdata = jts.createciphermsgs( len(jt65data), stegmsg, "OTP", "I LOVE SECURITY AND STUFF", "", "", False) finalmsgs = jts.steginject(jt65data, i, cipherdata, hidekey, False) # Decode finalmsgscopy = copy.deepcopy(finalmsgs) jt65stegmsgs = [] decodedjt65msgs = jts.decodemessages(finalmsgs, False) for i in range(len(finalmsgscopy)): if jts.validatesteg(decodedjt65msgs[i], finalmsgscopy[i], hidekey, STEG_DETECTION_ERROR_THRESHOLD, False): jt65stegmsgs.append(finalmsgscopy[i]) stegdata = jts.retrievesteg(jt65stegmsgs, hidekey, False) resultstegmsg = jts.deciphersteg( stegdata, "OTP", "I LOVE SECURITY AND STUFF", "", False) self.assertEqual(len(decodedjt65msgs), len(jt65msgs)) for i in range(len(jt65msgs)): self.assertEqual( jt65msgs[i].rstrip(), decodedjt65msgs[i].rstrip()) self.assertEqual(stegmsg.rstrip(), resultstegmsg.rstrip())
def test_OTP(self): for i in range(MAX_COVER_NOISE): # Encode jt65msgs = ["KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44", "KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44"] jt65data = jts.jt65encodemessages(jt65msgs, False) stegmsg = "BEACON FTW AND DEF CON 22" key = ''.join(random.choice(string.ascii_letters + string.digits) for n in xrange(random.randint(10, 30))) hidekey = jts.getnoisekey(key) cipherdata = jts.createciphermsgs( len(jt65data), stegmsg, "OTP", "I LOVE SECURITY AND STUFF", "", "", False) finalmsgs = jts.steginject(jt65data, i, cipherdata, hidekey, False) # Decode finalresultmsgs = list(finalmsgs) stegdata = jts.retrievesteg(finalmsgs, hidekey, False) resultstegmsg = jts.deciphersteg( stegdata, "OTP", "I LOVE SECURITY AND STUFF", "", False) decodedjt65msgs = jts.decodemessages(finalmsgs, False) self.assertEqual(len(decodedjt65msgs), len(jt65msgs)) for i in range(len(jt65msgs)): self.assertEqual( jt65msgs[i].rstrip(), decodedjt65msgs[i].rstrip()) self.assertEqual(stegmsg.rstrip(), resultstegmsg.rstrip())
def test_DecipherSteg_None(self): stegdata = [ np.array([ 47, 44, 14, 33, 4, 58, 19, 6, 16, 52, 50, 11, 6, 13, 41, 26, 39, 15, 39, 11 ]), np.array([ 22, 29, 9, 53, 17, 23, 57, 14, 20, 36, 39, 11, 59, 23, 28, 16, 53, 8, 57, 0 ]) ] result = jts.deciphersteg(stegdata, "none", "", "", False) self.assertEqual(result.rstrip(), "BEACON FTW AND DEF CON 22")
def test_AES_CFB_WAV(self): for i in range(MAX_COVER_NOISE): # Encode jt65msgs = [ "KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44", "KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44" ] jt65data = jts.jt65encodemessages(jt65msgs, False) stegmsg = "DEF CON 22" key = ''.join( random.choice(string.ascii_letters + string.digits) for n in xrange(random.randint(10, 30))) hidekey = jts.getnoisekey(key) cipherdata = jts.createciphermsgs( len(jt65data), stegmsg, "AES", "AES is totes secure, right? Yeah", "", "CFB", False) finalmsgs = jts.steginject(jt65data, i, cipherdata, hidekey, False) for index, value in enumerate(finalmsgs): tones = jt65sound.toneswithsync(value) jt65sound.outputwavfile("test_output-00" + str(index) + ".wav", tones) # Decode result1 = jt65sound.inputwavfile("test_output-000.wav") result2 = jt65sound.inputwavfile("test_output-001.wav") result3 = jt65sound.inputwavfile("test_output-002.wav") result4 = jt65sound.inputwavfile("test_output-003.wav") symbols1, confidence1, wavmsg1, s2db, freq, a1, a2 = result1[0] symbols2, confidence2, wavmsg2, s2db, freq, a1, a2 = result2[0] symbols3, confidence3, wavmsg3, s2db, freq, a1, a2 = result3[0] symbols4, confidence4, wavmsg4, s2db, freq, a1, a2 = result4[0] os.remove("test_output-000.wav") os.remove("test_output-001.wav") os.remove("test_output-002.wav") os.remove("test_output-003.wav") finalresultmsgs = [symbols1, symbols2, symbols3, symbols4] stegdata = jts.retrievesteg(finalresultmsgs, hidekey, False) resultstegmsg = jts.deciphersteg( stegdata, "AES", "AES is totes secure, right? Yeah", "CFB", False) decodedjt65msgs = jts.decodemessages(finalresultmsgs, False) self.assertEqual(len(result1), 1) self.assertEqual(len(result2), 1) self.assertEqual(len(result3), 1) self.assertEqual(len(result4), 1) self.assertEqual(len(decodedjt65msgs), len(jt65msgs)) for i in range(len(jt65msgs)): self.assertEqual(jt65msgs[i].rstrip(), decodedjt65msgs[i].rstrip()) self.assertEqual(stegmsg.rstrip(), resultstegmsg.rstrip())
def getstegresult(stegcollection, cipher, key, aesmode, verbose): # Decodes an entire series of steg messages, or notifies you if you have # some steg messages but are awaiting more transmissions to decode if cipher == "none": return ( True, "", True, jts.deciphersteg(stegcollection, cipher, key, aesmode, verbose, False), ) # Steg has already been unprepped else: localarray = stegcollection[0] if verbose: print "localarray : " + str(localarray) localarray = jts.jt65tobytes(localarray) if getstatusbyte(localarray) & 0x80 != 0x80: # The first packet in the collection does not represet a 'start' # packet, reset the collection and catch the next one return False, "Monitored steg mid-transmission, resetting for next transmission.", True, "" # The first packet represents a 'start' packet, do we have all the # packets? expectedpackets = getstatusbyte(localarray) & 0x7F if expectedpackets <= len(stegcollection): return True, "", True, jts.deciphersteg(stegcollection, cipher, key, aesmode, verbose, False) # The multi-packet transmission is not complete yet return ( False, "(" + str(len(stegcollection)) + "/" + str(expectedpackets) + ") total packets received.", False, "", )
def test_DecipherSteg_AES_ECB(self): stegdata = [ np.array([ 36, 4, 41, 24, 13, 59, 33, 52, 61, 58, 34, 51, 24, 42, 33, 50, 5, 13, 40, 61 ]), np.array([ 21, 19, 6, 19, 31, 6, 40, 34, 11, 4, 26, 16, 4, 8, 4, 62, 44, 32, 25, 61 ]) ] result = jts.deciphersteg(stegdata, "AES", "AES is totes secure, right? Yeah", "ECB", False) self.assertEqual(result.rstrip(), "DEF CON 22")
def test_DecipherSteg_ARC4(self): stegdata = [ np.array([ 1, 19, 25, 35, 19, 32, 46, 12, 62, 60, 24, 53, 21, 33, 29, 1, 1, 11, 38, 47 ]), np.array([ 60, 22, 15, 21, 4, 42, 5, 24, 16, 48, 46, 5, 14, 48, 32, 50, 5, 17, 27, 41 ]) ] result = jts.deciphersteg( stegdata, "ARC4", "RC4 is the most secure algorithm in the world", "", False) self.assertEqual(result.rstrip(), "DEF CON 22")
def test_OTP_Extra(self): for i in range(MAX_COVER_NOISE): # Encode with more JT65 msgs than necessary jt65msgs = [ "KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44", "KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44", "KB2BBC KA1AAB DD44", "KA1AAB KB2BBC DD44" ] jt65data = jts.jt65encodemessages(jt65msgs, False) stegmsg = "BEACON FTW AND DEF CON 22" key = ''.join( random.choice(string.ascii_letters + string.digits) for n in xrange(random.randint(10, 30))) hidekey = jts.getnoisekey(key) cipherdata = jts.createciphermsgs(len(jt65data), stegmsg, "OTP", "I LOVE SECURITY AND STUFF", "", "", False) finalmsgs = jts.steginject(jt65data, i, cipherdata, hidekey, False) # Decode finalmsgscopy = copy.deepcopy(finalmsgs) jt65stegmsgs = [] decodedjt65msgs = jts.decodemessages(finalmsgs, False) for i in range(len(finalmsgscopy)): if jts.validatesteg(decodedjt65msgs[i], finalmsgscopy[i], hidekey, STEG_DETECTION_ERROR_THRESHOLD, False): jt65stegmsgs.append(finalmsgscopy[i]) stegdata = jts.retrievesteg(jt65stegmsgs, hidekey, False) resultstegmsg = jts.deciphersteg(stegdata, "OTP", "I LOVE SECURITY AND STUFF", "", False) self.assertEqual(len(decodedjt65msgs), len(jt65msgs)) for i in range(len(jt65msgs)): self.assertEqual(jt65msgs[i].rstrip(), decodedjt65msgs[i].rstrip()) self.assertEqual(stegmsg.rstrip(), resultstegmsg.rstrip())
jt65stegmsgs = [] # Retrieve JT65 valid messages jt65msgs = jts.decodemessages(jt65data, args.verbose) if STEG_ENABLED: for i in range(len(jt65datacopy)): if jts.validatesteg(jt65msgs[i], jt65datacopy[i], hidekey, STEG_DETECTION_ERROR_THRESHOLD, args.verbose): jt65stegmsgs.append(jt65datacopy[i]) stegpresent = True # Retrieve steg message stegdata = jts.retrievesteg(jt65stegmsgs, hidekey, args.verbose) # Decipher steg message stegmsg = jts.deciphersteg(stegdata, args.cipher, args.key, args.aesmode, args.verbose) # Print result for index, value in enumerate(jt65msgs): print "\nDecoded JT65 message " + str(index) + " : " + colorama.Fore.BLUE + value + colorama.Fore.RESET if stegpresent: print "\nHidden message : " + colorama.Fore.RED + stegmsg + colorama.Fore.RESET # Interactive - Just listening for now elif args.interactive: stegcollection = [] while True: # Wait for start of minute print "Waiting for start of minute..." while datetime.datetime.now().second != 0:
# Retrieve JT65 valid messages jt65msgs = jts.decodemessages(jt65data, args.verbose) if STEG_ENABLED: for i in range(len(jt65datacopy)): if jts.validatesteg(jt65msgs[i], jt65datacopy[i], hidekey, STEG_DETECTION_ERROR_THRESHOLD, args.verbose): jt65stegmsgs.append(jt65datacopy[i]) stegpresent = True # Retrieve steg message stegdata = jts.retrievesteg(jt65stegmsgs, hidekey, args.verbose) # Decipher steg message stegmsg = jts.deciphersteg(stegdata, args.cipher, args.key, args.aesmode, args.verbose) # Print result for index, value in enumerate(jt65msgs): print "\nDecoded JT65 message " + str( index) + " : " + colorama.Fore.BLUE + value + colorama.Fore.RESET if stegpresent: print "\nHidden message : " + colorama.Fore.RED + stegmsg + colorama.Fore.RESET # Interactive - Just listening for now elif args.interactive: stegcollection = [] while True: # Wait for start of minute print "Waiting for start of minute..."