PNG Number (100 pts)

Solved by: sardinachanx, zookham

Problem:

Calculate the sum of decimal digits of the number represented in big-endian by the raw pixel data of number.png in BGR byte order.

Files:

number.png

Hint:

Patience.

Solution:

Very typical algo problem! The question looks relatively straight-forward - after looking up the exact definition of big endian I coded up a solution, with one caveat. Using the Java inbuilt arbitrary precision integer library (BigInteger), the solution ran for 6 hours. Towards the end of the competition (when they fixed the flag), I didn't have much time left and our current answers were somehow wrong, so I ended up using another AP integer library (APInt) to code up the solution. That reduced the runtime of the entire solution to under 3 minutes. I also split the solution up into two parts so I could resume my progress at a particular point.

Code:

Reading in the raw RGB data from the png

import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.imageio.ImageIO;

public class JPEGNumber {
    public static void main(String[]args){
        BufferedWriter bw = null;
        try {
            BufferedImage image = ImageIO.read(new File("number.png"));
            int width = image.getWidth();
            int height = image.getHeight();
            int[] all = image.getRGB(0, 0, width, height, null, 0, image.getWidth());
            System.out.println("I'm done with reading!");
            StringBuilder sb = new StringBuilder();

            for(int y = 0; y < height; y++){
                for(int x = 0; x < width; x++){
                int current = all[y * width + x];
                int colorRed = (current >> 16) & 0xFF; 
                int colorGreen = (current >> 8) & 0xFF; 
                int colorBlue = (current) & 0xFF; 
                sb.append(pad(Integer.toHexString(colorBlue)));
                sb.append(pad(Integer.toHexString(colorGreen)));
                sb.append(pad(Integer.toHexString(colorRed)));
                }
            }
            File output = new File("hex.txt");
            try{
                bw = new BufferedWriter(new FileWriter(output));
                bw.write(sb.toString());
            }
            catch(IOException e){
                e.printStackTrace();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(bw != null){
                try{
                    bw.close();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

    public static String pad(String s){
        if(s.length() == 0){
            return "00";
        }
        else if(s.length() == 1){
            return "0" + s;
        }
        else{
            return s;
        }
    }

}

Converting the output hex from above to a decimal number and finding the digital root

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import org.apfloat.Apint;

public class PNGRead {
    public static void main(String[]args){
        BufferedReader br = null;
        BufferedWriter bw = null;
        try{
            br = new BufferedReader(new FileReader(new File("hex.txt")));
            String s = br.readLine();
            Apint bi = new Apint(s, 16);
            System.out.println("int created");
            try{
                bw = new BufferedWriter(new FileWriter(new File("dec.txt")));
                String dec = bi.toRadix(10).toString(true);
                bw.write(dec);
                System.out.println("done");
                long count = 0;
                long length = dec.length();
                for(int i = 0; i < length; i++){
                    if(i > length - 2){
                        System.out.println(dec.substring(i, i + 1));
                    }
                    count += Integer.parseInt(dec.substring(i, i + 1));
                }
                System.out.println(count);
            }
            catch(IOException e){
                e.printStackTrace();
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }
        finally{
            if(br != null){
                try{
                    br.close();
                } catch(IOException e){
                    e.printStackTrace();
                }
            }
            if(bw != null){
                try{
                    bw.close();
                } catch(IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
}

FLAG: sctf{102261653}