Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Snapchat Image Decrypt - This Ruby script decrypts the blob received from the `bq/blob` endpoint. Many thanks to @kivikakk, @adamcaudill, @tlack, and @NeilHanlon for inspiration, code, guides, and of course, the encryption key.
#!/usr/bin/env ruby
require 'openssl'
data = File.open('blob', 'r:ASCII-8BIT').read
c = OpenSSL::Cipher.new('AES-128-ECB')
c.decrypt
c.key = 'M02cnQ51Ji97vwT4'
o = ''.force_encoding('ASCII-8BIT')
data.bytes.each_slice(16) { |s| o += c.update(s.map(&:chr).join) }
o += c.final
File.open('blob.jpg', 'w') { |f| f.write(o) }
@jamescmartinez
Copy link
Author

jamescmartinez commented Jul 30, 2014

Checking! @donaldsr

@jamescmartinez
Copy link
Author

jamescmartinez commented Jul 30, 2014

I wish Github gists had notifications...

@ClayF
Copy link

ClayF commented Aug 13, 2014

Any updates in the "wrong final block length" error?

@royalelee
Copy link

royalelee commented Aug 15, 2014

Im at the same thing as everyone else now wrong final block length

@royalelee
Copy link

royalelee commented Aug 15, 2014

Now bad decrypt lol

@donaldsr
Copy link

donaldsr commented Aug 18, 2014

Any updates on this?

@royalelee, what did you do to get the bad decrypt error?

@royalelee
Copy link

royalelee commented Aug 20, 2014

Mine is line 11 bad decrypt cipher error

@royalelee
Copy link

royalelee commented Aug 20, 2014

aka the line with final output in it

@donaldsr
Copy link

donaldsr commented Aug 27, 2014

Still nothing? :)

@mwarzynski
Copy link

mwarzynski commented Sep 14, 2014

snap.rb:11:in `final': bad decrypt (OpenSSL::Cipher::CipherError)
        from snap.rb:11:in `<main>'

I googled for the solution - just need to add one line:

c.decrypt
c.padding = 0 # I added this line
c.key = 'M02cnQ51Ji97vwT4'

Unfortunately it only decrypts old snaps. Stuff from today can't be read by image viewer.
(SnapChat version: 5.0.34.6)

Actually, there is a small difference (char "_-_") between filenames:
Decryption working: h1a81hurcs00h1088514799151508741.jpg.nomedia
Decryption not working: h1a81hurcs00h-1948520179053141815.jpg.nomedia

No error message.


Anyone could help?

@donaldsr
Copy link

donaldsr commented Sep 15, 2014

@inxmen, i assume you tried remove the dash in the filename and run it, with the same result? If you get no error message at all it's kinda hard to find a solution, atleast im lost when you have nothing to go on. Anyone else?

@mwarzynski
Copy link

mwarzynski commented Sep 15, 2014

@donaldsr, Of course I tried. No error message.

ruby -v
ruby 2.0.0p353 (2013-11-22 revision 43784) [x86_64-linux]

@donaldsr
Copy link

donaldsr commented Sep 15, 2014

Strange that it does not produce any error message at all.. any idea why? They probably did change the key but that would definitely produce some sort of error message.. Im not that well versed in ruby but is there a way to turn on some sort of deeper debugging to see what is going on? Might be able to set this up on my lab machine some time during the week to see if i can reproduce this.

@mwarzynski
Copy link

mwarzynski commented Sep 15, 2014

I changed key to wrong one - there is no warning or message. Script has generated invalid file.
I can't debug ruby - I am beginner in this language. Maybe tomorrow I will find some time to figure it out.

Anybody know where is stored AES key?

@arcaneiceman
Copy link

arcaneiceman commented Sep 26, 2014

i know where it is... i tested the apk v 5.0.34 easiest way it to decompile it in java code and search for it as a string. its really hard to miss

@arcaneiceman
Copy link

arcaneiceman commented Sep 26, 2014

also, the latest apk does use this but the code snippet isnt working :( anyone figure the problem out yet? yes i get same wrong final block length problem.When i added padding as 0, it said data not a multiple of block length

@mgrandi
Copy link

mgrandi commented Oct 31, 2014

I have my own snapchat decrypting stuff (https://dl.dropboxusercontent.com/u/962389/mgrandi_snapchat_example.zip), which requires python3 and pycrypto. try editing example.py with your username and password and then running it. (make sure you have an unopened snap from someone, you can send a snap to yourself i think, or else it won't work and it will say the file was already deleted).

I just sent a snap to myself and used the above code to decrypt it, and it did work and did produce a correct JPG, but some guy sent me some .jpg.nomedia files that don't seem to work with this decryption / key .....Both that ruby code and my own script produce the same thing, which isn't a JPEG file (it doesn't start with b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01')... so i'm pretty confused on whats going on.

maybe its sending it under a different encryption if it detects the app is a certain version? or perhaps they updated the key? Is the android client modifying the data when its saving it to a .nomedia to prevent people from getting it off the phone? My code just downloads it straight from the snapchat server, which would be why mine works fine but these .nomedia files don't work...

@DavePlater
Copy link

DavePlater commented Nov 17, 2014

Using your ruby example I have made a working C# version.

public static void AesDecryptSnap(string infilename, string outfilename)
{ File.WriteAllBytes(outfilename, AesDecryptSnap(infilename)); }
public static byte[] AesDecryptSnap(string infilename)
{
            byte[] retval = new byte[0];
            byte[] keyAndIvBytes = UTF8Encoding.UTF8.GetBytes("M02cnQ51Ji97vwT4");

            RijndaelManaged algorithm = new RijndaelManaged();
            //set the mode, padding and block size
            algorithm.Padding = PaddingMode.None;
            algorithm.Mode = CipherMode.ECB;
            algorithm.KeySize = 128;
            algorithm.BlockSize = 128;

            using (FileStream inStream = File.OpenRead(infilename))
            {
                using (CryptoStream cryptoStream = new CryptoStream(inStream, algorithm.CreateDecryptor(keyAndIvBytes, keyAndIvBytes), CryptoStreamMode.Read))
                {
                    using (MemoryStream outStream = new MemoryStream())
                    {
                        CopyStream(cryptoStream, outStream);
                        retval = outStream.ToArray();
                    }
                }
            }
            algorithm.Clear();

            return retval;
}
public static void CopyStream(Stream input, Stream output)
{
            byte[] b = new byte[32768];
            int r;
            while ((r = input.Read(b, 0, b.Length)) > 0)
            { output.Write(b, 0, r); output.Flush(); }
}

I also have a version ported to java/android, but it is still untested.

@daskog
Copy link

daskog commented Nov 25, 2014

Any update for the latest version of Snapchat? I see there is a update on the python version that takes care of the new encryption implementation introduced in later version of Snapchat, md5, etc.

@asad-awadia
Copy link

asad-awadia commented Dec 30, 2014

Updates? Did anyone solve the error?
`final': wrong final block length (OpenSSL::Cipher::CipherError)

@jvkassi
Copy link

jvkassi commented Jan 10, 2015

This is no more working

@Amaterasu27
Copy link

Amaterasu27 commented Mar 21, 2015

M02cnQ51Ji97vwT4 is the old key
Need to find the new one

@sampellino
Copy link

sampellino commented Apr 19, 2015

Any update on this?

@Daniellsantamaria
Copy link

Daniellsantamaria commented May 9, 2015

snapchat_decrypt.rb Raw
1
2
3
4
5
6
7
8
9
10
11
12

!/usr/bin/env ruby

require 'openssl'

data = File.open('blob', 'r:ASCII-8BIT').read
c = OpenSSL::Cipher.new('AES-128-ECB')
c.decrypt
c.key = 'M02cnQ51Ji97vwT4'
o = ''.force_encoding('ASCII-8BIT')
data.bytes.each_slice(16) { |s| o += c.update(s.map(&:chr).join) }
o += c.final
File.open('blob.jpg', 'w') { |f| f.write(o) }

@Daniellsantamaria
Copy link

Daniellsantamaria commented May 9, 2015

Thank you for posting this code. I had a number of snapchat files to decrypt so added A loop
Snapchat = Dir["*.jpg.nomedia"]
Snapchat.each {joysantamaria
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

!/usr/bin/env ruby

require 'openssl'

data = File.open('blob', 'r:ASCII-8BIT').read
c = OpenSSL::Cipher.new('AES-128-ECB')
c.decrypt
c.key = 'M02cnQ51Ji97vwT4'
o = ''.force_encoding('ASCII-8BIT')
data.bytes.each_slice(16) { |s| o += c.update(s.map(&:chr).join) }
o += c.final
File.open('blob.jpg', 'w') { |f| f.write(o) }

@socalchs
Copy link

socalchs commented Jun 4, 2015

Can anyone walk me through this? From plugging in my phone into the computer(im guessing thats what youre supposed to (thats how lost I am)) to viewing the files. I'll give you a couple bucks through paypal if someone can do it and it works. Thanks!

@jordan64000
Copy link

jordan64000 commented Jul 3, 2015

key : M02cnQ51Ji97vwT4 is dead :'(

@grx11
Copy link

grx11 commented Aug 5, 2015

well, i would like that someone in this damn world teach this on video or something i just lost at least 28 photos of my story that couldn't be publicated still don't know why D: i'm so frustated right now... ): i tried everything D:

@betrisey
Copy link

betrisey commented Sep 6, 2015

The blob files are no longer encrypted, you just have to add the extension .jpg

@luanagelmi
Copy link

luanagelmi commented Aug 31, 2017

Please help me
I do not understand much about these matters
What should I do with this code?
@jamescmartinez

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment