Sigueme en Facebook Sigueme en Twitter Sigueme en Instagram Sigueme en Youtube
JC Mouse Bolivia
Index / Java / Cifrado francmasón PigPen

Cifrado francmasón PigPen

Autor jc mouse domingo, agosto 16, 2015

El cifrado francmasón es un cifrado por sustitución simple que cambia las letras por símbolos. Sin embargo, el uso de símbolos no impide el criptoanálisis, y el criptoanálisis es idéntico al de otros métodos de cifrado por substitución simple.

Llamado también “cifra Pigpen” este método de cifrado fue utilizado por los masones en el siglo XVIII para preservar la privacidad de sus archivos. Se basa en la sustitución de cada letra por un símbolo de acuerdo al siguiente modelo:

cifrado simple

Para codificar una letra en particular, se debe encontrar su posición en una de las cuatro cuadrículas y luego se dibuja esa porción de la cuadrícula para representar esa letra. Por tanto el mensaje “HOLA MUNDO” cifrado bajo este sistema tendría la siguiente forma:

hola pigpen

Otro ejemplo un poco mas largo, es  el siguiente, el juramento de la Guardia Nocturna de la serie Juegos de Tronos:

Escuchad mis palabras, sed testigos de mi juramento.
La noche se avecina, ahora empieza mi guardia.
No terminará hasta el día de mi muerte.
No tomaré esposa, no poseeré tierras, no engendraré hijos.
No llevaré corona, no alcanzaré la gloria.
Viviré y moriré en mi puesto.
Soy la espada en la oscuridad.
Soy el vigilante del Muro.
Soy el fuego que arde contra el frío,
la luz que trae el amanecer,
el cuerno que despierta a los durmientes,
el escudo que defiende los reinos de los hombres.
Entrego mi vida y mi honor a la Guardia de la Noche,
durante esta noche y todas las que estén por venir.

Este texto cifrado, tiene la siguiente forma:

juramento guardia nocturna

Proyecto Java

https://youtu.be/zeX-Oh_-x5c

Las clases principales son:

  • Clase Letter: Se encarga de dibujar las letras A..Z  cifradas y en su estado normal
  • Clase Sheet: Se extiende de un JPanel y nos sirve de lienzo para pintar el mensaje cifrado

Clase Letter

package com.bolivia.pigpen;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Stroke;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

/**
 * @web http://www.jc-mouse.net/
 * @author Mouse
 */
public class Letter {
    
    private Point point                 =       new Point(0,0);
    private final int SIZE_BOX          =       24;
    //tamaño y posicion de letra 
    private int x                       =       0;
    private int y                       =       0;
    private final int WIDTH             =       16;
    private final int HEIGHT            =       16;   
    //
    private final Font FONT_CHAR        =       new Font("Tahoma", Font.BOLD, 16 );
    private Dimension dimensionText;
    private String letter               =       "A";    
    private final Color COLOR_CHAR            =       new Color(0,0,0);
    private final Stroke STROKE_CHAR    =       new BasicStroke(2f);
    private final Stroke STROKE_0       =       new BasicStroke(0);
    
    /**
     * Constructor de clase
     * @param letter letra de A..Z o cualquier otro caracter, si no es A..z no se cifra
     */
    public Letter(String letter){
        this.letter = letter;
        x = point.x+4;
        y = point.y+4;     
    }
    
    /**
     * Constructor de clase
     * @param letter letra de A..Z o cualquier otro caracter, si no es A..z no se cifra
     * @param point coordenada X,Y de letra/caracter
     */
    public Letter(String letter, Point point){
        this.letter = letter.toUpperCase();
        this.point = point;
        x = point.x+4;
        y = point.y+4;        
    }
    
    /**
     * Metodo para pintar una letra pigpen/caracter 
     * @param g2
     */
    public void drawLetter(Graphics2D g2){                  
        g2.setStroke(STROKE_CHAR);        
        g2.setColor( COLOR_CHAR );
        if(letter.equals("A") || letter.equals("J") ){
            g2.drawLine(x, y+HEIGHT, x+WIDTH, y+HEIGHT); //  _
            g2.drawLine(x+WIDTH, y, x+WIDTH, y+HEIGHT);  //   |
            if(letter.equals("J")){
                g2.setStroke(STROKE_0);   
                g2.fillRect(x+WIDTH-8, y+HEIGHT-8,6, 6);    
            }            
        } else if(letter.equals("B") || letter.equals("K") ){            
            g2.drawLine(x, y, x, y+HEIGHT);              // |
            g2.drawLine(x, y+HEIGHT, x+WIDTH, y+HEIGHT); //  _       
            g2.drawLine(x+WIDTH, y, x+WIDTH, y+HEIGHT);  //   |     
            if(letter.equals("K")){
                g2.setStroke(STROKE_0);
                g2.fillRect(x+WIDTH/2-3, y+HEIGHT-8,6, 6);    
            }            
        } else if(letter.equals("C") || letter.equals("L")){            
            g2.drawLine(x, y, x, y+HEIGHT);              // |
            g2.drawLine(x, y+HEIGHT, x+WIDTH, y+HEIGHT); // _                    
            if(letter.equals("L")){
                g2.setStroke(STROKE_0); 
                g2.fillRect(x+2, y+HEIGHT-8,6, 6);    
            }    
        } else if(letter.equals("D") || letter.equals("M")){            
            g2.drawLine(x, y, x+WIDTH, y);               // -       
            g2.drawLine(x, y+HEIGHT, x+WIDTH, y+HEIGHT);        
            g2.drawLine(x+WIDTH, y, x+WIDTH, y+HEIGHT);            
            if(letter.equals("M")){
                g2.setStroke(STROKE_0);    
                g2.fillRect(x+WIDTH-8, y+HEIGHT/2-3,6, 6);    
            }    
        }else if(letter.equals("E") || letter.equals("N")){            
            g2.drawLine(x, y, x+WIDTH, y);               // -
            g2.drawLine(x, y, x, y+HEIGHT);              // |
            g2.drawLine(x, y+HEIGHT, x+WIDTH, y+HEIGHT); //  _       
            g2.drawLine(x+WIDTH, y, x+WIDTH, y+HEIGHT);  //   |          
             if(letter.equals("N")){
                g2.setStroke(STROKE_0); 
                g2.fillRect(x+WIDTH/2-3, y+HEIGHT-8,6, 6);    
            }  
        }else if(letter.equals("F") || letter.equals("O")){            
            g2.drawLine(x, y, x+WIDTH, y);               // -
            g2.drawLine(x, y, x, y+HEIGHT);              // |
            g2.drawLine(x, y+HEIGHT, x+WIDTH, y+HEIGHT); //  _                      
            if(letter.equals("O")){
                g2.setStroke(STROKE_0);  
                g2.fillRect(x+2, y+HEIGHT/2-3,6, 6);    
            }   
        }else if(letter.equals("G") || letter.equals("P")){            
            g2.drawLine(x, y, x+WIDTH, y);               // -                         
            g2.drawLine(x+WIDTH, y, x+WIDTH, y+HEIGHT);            
            if(letter.equals("P")){
                g2.setStroke(STROKE_0); 
                g2.fillRect(x+WIDTH-8, y+2,6, 6);    
            }  
        }else if(letter.equals("H") || letter.equals("Q")){            
            g2.drawLine(x, y, x+WIDTH, y);               // -
            g2.drawLine(x, y, x, y+HEIGHT);              // |               
            g2.drawLine(x+WIDTH, y, x+WIDTH, y+HEIGHT);  //   |            
            if(letter.equals("Q")){
                g2.setStroke(STROKE_0);
                g2.fillRect(x+WIDTH/2-3, y+2,6, 6);    
            }  
        }else if(letter.equals("I") || letter.equals("R")){            
            g2.drawLine(x, y, x+WIDTH, y);               // -
            g2.drawLine(x, y, x, y+HEIGHT);              // |            
            if(letter.equals("R")){
                g2.setStroke(STROKE_0);    
                g2.fillRect(x+2, y+2,6, 6);    
            }  
        }else if(letter.equals("T") || letter.equals("X")){    //>        
            g2.drawLine(x, y, x+WIDTH, y+HEIGHT/2);               
            g2.drawLine(x, y+HEIGHT, x+WIDTH, y+HEIGHT/2);               
            if(letter.equals("X")){
                g2.setStroke(STROKE_0); 
                g2.fillRect(x, y+HEIGHT/2-3,6, 6);    
            }
        }else if(letter.equals("U") || letter.equals("Y")){ //<
            g2.drawLine(x, y+HEIGHT/2, x+WIDTH, y);               
            g2.drawLine(x, y+HEIGHT/2, x+WIDTH, y+HEIGHT);               
            if(letter.equals("Y")){
                g2.setStroke(STROKE_0); 
                g2.fillRect(x+WIDTH-6, y+HEIGHT/2-3,6, 6);    
            }
        }else if(letter.equals("S") || letter.equals("W")){ // \/
            g2.drawLine(x, y, x+WIDTH/2, y+HEIGHT);               
            g2.drawLine(x+WIDTH, y, x+WIDTH/2, y+HEIGHT);               
            if(letter.equals("W")){
                g2.setStroke(STROKE_0); 
                g2.fillRect(x+WIDTH/2-3, y,6, 6);    
            }
        }else if(letter.equals("V") || letter.equals("Z")){ // /\
            g2.drawLine(x+WIDTH/2, y, x, y+HEIGHT);               
            g2.drawLine(x+WIDTH/2, y, x+WIDTH, y+HEIGHT);               
            if(letter.equals("Z")){
                g2.setStroke(STROKE_0); 
                g2.fillRect(x+WIDTH/2-3, y+HEIGHT-8,6, 6);    
            }
        }else{// si no corresponde a ninguna letra de A..Z pinta el original 
            //que puede ser una letra con acento, un numero u otro caracter especial            
            if(letter.length()>0){
                dimensionText = calculateFontDimension(letter);
                g2.setFont(FONT_CHAR); 
                g2.drawString( letter, point.x+SIZE_BOX/2-dimensionText.width/2, point.y + SIZE_BOX/2 + dimensionText.height/2);    
            }            
        }
        
    }
  
    /**
     * Pinta una letra de A..Z en java2d
     * @param g2
     */
    public void paintLetter(Graphics2D g2){          
        g2.setColor( COLOR_CHAR );
        dimensionText = calculateFontDimension(letter);
        g2.setFont(FONT_CHAR); 
        g2.drawString( letter, point.x+SIZE_BOX/2-dimensionText.width/2, point.y + SIZE_BOX/2 + dimensionText.height/2);    
    }
        
    /**
     * Metodo que retorna una imagen 
     * @param band si
     *  TRUE: retorna letra cifrada
     *  FALSE: retorna letra sin cifrar
     * @return BufferedImage
     */
    public BufferedImage getImage(boolean band){
        BufferedImage bufferedImage = new BufferedImage(SIZE_BOX, SIZE_BOX, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = bufferedImage.createGraphics();
        g2d.setColor( new Color(255,255,255));   
        g2d.fill(new Rectangle2D.Double(0,0,SIZE_BOX,SIZE_BOX)); 
        if(band)
            drawLetter(g2d);
        else
            paintLetter(g2d);
        g2d.dispose();
        return bufferedImage;
    }
    
    
    /**
     * Obtiene las dimensiones de un texto
     * @param text          
     * @return Dimension
    */
    public Dimension calculateFontDimension(String text){       
            BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = image.createGraphics();            
            g2.setStroke(STROKE_0);            
            TextLayout layout = new TextLayout(text, FONT_CHAR, g2.getFontRenderContext());
            layout.draw(g2, 0, 0);
            Rectangle2D bounds = layout.getBounds();
            bounds.setRect(bounds.getX(),
                  bounds.getY(),
                  bounds.getWidth(),
                  bounds.getHeight());
            int w = (int) bounds.getWidth();
            int h = (int) bounds.getHeight();            
            g2.draw(bounds);
            g2.dispose();
            return new Dimension(w,h);
    }
    
}//Letter:end

Clase Sheet

package com.bolivia.pigpen;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 * @web http://ww.jc-mouse.net/
 * @author Mouse
 */
public class Sheet extends JPanel {
    
    private final String[] APLHA_ARRAY      =       {"A","B","C","D","E","F","G","H","I","J","K","L",
                                                     "M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
    private List<Letter> letterList         =       new ArrayList<Letter>();         
    private final int MAX_NUM_COLUMN        =       32;    
    private final int SIZE_BOX              =       24;
    private final Color BG_COLOR            =       new Color(255,255,255);
    private Dimension dimension;
    private BufferedImage bufferedImage     =       null;
    private int heightSheet=0;
    private int widthSheet=0;
    
    /**Constructor de clase */
    public Sheet(){
        super();
        dimension = new Dimension(100,100);
        Sheet.this.setBackground(BG_COLOR);
        Sheet.this.setSize(dimension);
        Sheet.this.setVisible(true);        
    }
    
    @Override
    public void paintComponent(Graphics g){
        Graphics2D g2 =(Graphics2D) g;        
        bufferedImage = new BufferedImage( widthSheet, heightSheet, BufferedImage.TYPE_INT_RGB );
        Graphics2D graphics2D = bufferedImage.createGraphics();        
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2D.setColor( BG_COLOR );
        graphics2D.fill(new Rectangle2D.Double(0,0,widthSheet,heightSheet)); 
        //pinta letras/caracter
        for(Letter l:letterList)
        {            
            l.drawLetter(graphics2D);            
        }
        g2.drawImage(bufferedImage, 0, 0, this);
        
    }
    
    /**
     * Metodo para escribir en disco
     * @param file
     */
    public void saveBufferedImage(File file){
        try {           
            if( bufferedImage!=null)
                ImageIO.write(bufferedImage, "png", file);            
	} catch (IOException e) {            
            System.err.println("IOException:" + e.getMessage());
	}
    }
    
    /**
     * Cifra una cadena de texto y añade letra cifrada en un arrayList
     * @param text texto a cifrar
     */
    public void cifrar(String text){
        String[] textArray = text.split("");        
        //elimina contenido
        letterList.clear();        
        int row=0;
        int col=0;
        //añade cada letra/caracter en un lista de objetos LETTER junto a su 
        //respectiva posicion en la matriz col x row
        for(String letter: textArray){            
            letterList.add( new Letter(letter, new Point(SIZE_BOX*col,SIZE_BOX*row)) );
            col++;
            if(col == MAX_NUM_COLUMN){
                col=0;
                row++;
            }            
        }        
        //redimensiona JPanel
        dimension = new Dimension(MAX_NUM_COLUMN*SIZE_BOX,SIZE_BOX*row);
        setPreferredSize(dimension);
        setSize(dimension);        
        heightSheet = SIZE_BOX*(row+1);     
        widthSheet = MAX_NUM_COLUMN*SIZE_BOX;
        repaint();        
    }
    
    /**
     * Metodo para descifrar el contenido de una imagen cifrado por PigPen
     * @param file
     */
    public void descifrar(File file){
        //genera un abecedario de imagenes cifradas
        BufferedImage[] alpha = new BufferedImage[APLHA_ARRAY.length];
        for(int i=0; i<APLHA_ARRAY.length;i++){
            Letter tmp = new Letter(APLHA_ARRAY[i]);
            alpha[i] = tmp.getImage(true);
        }
        //genera un abecedario de imagenes no cifradas
        BufferedImage[] abc = new BufferedImage[APLHA_ARRAY.length];
        for(int i=0; i<APLHA_ARRAY.length;i++){
            Letter tmp = new Letter(APLHA_ARRAY[i]);
            abc[i] = tmp.getImage(false);
        }        
        //lee imagen de archivo
        try {        
            BufferedImage bImage = ImageIO.read(file);             
            //validacion
            if(bImage.getWidth()<SIZE_BOX*MAX_NUM_COLUMN || bImage.getHeight()<SIZE_BOX ){
                JOptionPane.showMessageDialog(null, "Error: La imagen es incorrecta");
                return;
            }
            //crea un array de imagenes extrayendo imagenes 24x24 de imagen principal
            int rows = bImage.getHeight()/SIZE_BOX;
            int cols = MAX_NUM_COLUMN;
            BufferedImage[] imageArray = new BufferedImage[rows * cols];                        
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    imageArray[(i * cols) + j] = bImage.getSubimage(j * SIZE_BOX, i * SIZE_BOX, SIZE_BOX,SIZE_BOX);
                }
            }
            //Array de imagenes destino, aqui se colocal las letras descifradas asi como otros caracteres
            BufferedImage[] imageArrayTarget = new BufferedImage[rows * cols];
            
            //compara el array de imagenes con array de imagenes A..Z cifradas y va colocando en array de imagenes destino
            for (int k = 0; k < imageArray.length; k++){
                int val=-1;
                for(int p=0; p<alpha.length;p++){//abcdario                    
                    double res = compare(imageArray[k],alpha[p]);                        
                    if( res < 1){                    
                        val = p;                    
                        break;
                    }         
                }
                if(val!=-1){
                    imageArrayTarget[k] = abc[val];
                }else{
                   imageArrayTarget[k] = imageArray[k]; 
                }
            }            
            
            //Crea una imagen en memoria 
            bufferedImage = new BufferedImage(SIZE_BOX*cols, SIZE_BOX*rows, BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics2D = bufferedImage.createGraphics();
            graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            graphics2D.setColor( BG_COLOR );
            graphics2D.fill(new Rectangle2D.Double(0,0,SIZE_BOX*cols,SIZE_BOX*rows)); 
            int col=0;
            int row=0;
            for(BufferedImage o:imageArrayTarget){
                graphics2D.drawImage(o, null, SIZE_BOX*col, row);    
                col++;
                if(col==MAX_NUM_COLUMN)
                {
                    col=0;
                    row +=SIZE_BOX;
                }
            }        
            //guarda imagen en disco
            try {    
                String absolutePath = file.getAbsolutePath();        
                String newPath = absolutePath .substring(0, absolutePath .length()-4) + "_" + System.currentTimeMillis() + ".png";                
                ImageIO.write(bufferedImage, "png", new File(newPath));            
                JOptionPane.showMessageDialog(null, "Save: " + newPath );                
                graphics2D.dispose();
            } catch (IOException e) {            
                System.err.println("IOException:" + e.getMessage());
            }             
        } catch (IOException ex) {
            System.err.println("IOException" + ex.getMessage());
        }
        
    }
    
    /**
     * Metodo para comparar imagenes
     * @param BufferedImage imagen 1
     * @param BufferedImage imagen 2
     * @return double mientras más alto es el valor de retorno las imagenes son menos iguales
     *    0 : imagene son iguales
     *  100 : las imagenes no son iguales
     * Fuente codigo: http://rosettacode.org/wiki/Percentage_difference_between_images
     */
    private double compare(BufferedImage img1, BufferedImage img2){
        int width1 = img1.getWidth(null);        
        int height1 = img1.getHeight(null);        
            long diff = 0;
            for (int y = 0; y < height1; y++) {
            for (int x = 0; x < width1; x++) {
              int rgb1 = img1.getRGB(x, y);
              int rgb2 = img2.getRGB(x, y);              
              diff += Math.abs(((rgb1 >> 16) & 0xff) - ((rgb2 >> 16) & 0xff));              
              diff += Math.abs(((rgb1 >>  8) & 0xff) - ((rgb2 >>  8) & 0xff));              
              diff += Math.abs(((rgb1      ) & 0xff) - ((rgb2      ) & 0xff));
            }
          }
          double n = width1 * height1 * 3;
          double p = diff / n / 255.0;          
          return p * 100.0;
    }
    
}//Sheet:end

Actualizado 23 de Mayo de 2018

Descargar proyecto Cifrado PigPen

App para Android: https://play.google.com/store/apps/details?id=net.jc_mouse.pigpen

pigpen Freemasons android

Enjoy!!!

Tags

Si te ha gustado podrías compartirlo o dejar un comentario. ¡Muchas gracias!
Autor: JC Mouse

Yo soy yo :) JC Mouse, Soy orgullosamente boliviano soy fundador y CEO de la web jc-Mouse.net uno de las pocas web en emprendimiento y tecnología en Bolivia.

Toda la información que encuentres en este sitio es y sera completamente gratis siempre, puedes copiar, descargar y re-publicar si así lo deseas en otros blogs o sitios web, solo te pido a cambio que dejes una referencia a esta web. Esto nos ayuda a crecer y seguir aportando. Bye

Enjoy! :)

También Te Podría Interesar

Capturar webcam con VB.NET

Capturar webcam con VB.NET

¿Que haremos? Crearemos una aplicación en Visual Studio, la cual hará uso de una webcam para capturar el video en frames...

Buscar y cargar imagenes de disco

Buscar y cargar imagenes de disco

Cuando se almacenan imágenes en una aplicación java y se desea después a modo de registro buscar estas y cargarlas en al...

Uso de BorderPane

Uso de BorderPane

BorderPane es un layout que distribuye los nodos hijos en 5 posiciones TOP, LEFT, BOTTOM, RIGHT y CENTER Los nodos hijos...

Envio de correo gmail con PHPMailer

Envio de correo gmail con PHPMailer

En este tutorial utilizaremos la librería PHPMailer para enviar correo electrónico utilizando el servidor de GMail de Go...

Introducción a la internacionalización de aplicaciones

Introducción a la internacionalización de aplicaciones

La internacionalización permite a las aplicaciones adaptarse a los diferentes idiomas y regiones sin necesidad de cambio...

Blog MVC en PHP (Código Fuente)

Blog MVC en PHP (Código Fuente)

En este post dejo el código fuente de un blog en PHP desarrollado siguiendo el patrón de diseño MVC (Modelo, Vista y Con...

Comparte lo que sabes

Categorias

Últimas entradas

Sans Forgetica es una fuente diseñada utilizando los principios de la psicología cognitiva para ayudar a recordar mejor...

Facebook la compañía de Mark Zuckerberg confirmó hace unas semanas que la Red Social había sido hackeado debido a una br...

Google+ o Google plus como también se le conoce a la red social del gigante de la informática Google cerrará para siempr...

Como dice un viejo dicho, “La practica hace al maestro” y en el mundo de la programación no es diferente, po...

Android Bolivia

MAUS