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 https://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

Te enseño como generar imagenes con Google Bard

Te enseño como generar imagenes con Google Bard

Google Bard la inteligencia artificial de Google se actualiza con una mejora que entra a competir con el resto de IAs y...

Gestión de productos – El modelo (Parte 4)

Gestión de productos – El modelo (Parte 4)

En la estructura del proyecto, nuestro modelo mvc esta compuesto por tres paquetes, la vista, el modelo y controlador. L...

Client REST usando GSON y Volley

Client REST usando GSON y Volley

En este post crearemos un cliente android para consumir un recurso de un REST API utilizando las librerías GSON y Volley...

Autenticación de usuarios bajo el patrón MVC

Autenticación de usuarios bajo el patrón MVC

MVC es un patrón de arquitectura de software que separa una aplicación en tres componentes lógicos principales.  Estos s...

SOAP .:. Cliente android

SOAP .:. Cliente android

En esta oportunidad construiremos una aplicación android que nos permitirá consumir  un servicio web utilizando la libre...

Laberinto del Terror (Código Fuente + juego)

Laberinto del Terror (Código Fuente + juego)

El laberinto del terror es un juego en el que haciendo uso del ratón y de tu pulso de borracho debes cruzar distintos la...

Comparte lo que sabes

Categorias

Últimas entradas

Si trabajas con redes sociales (RRSS) a continuación te muestro tres herramintas gratuitas que te ayudaran a la hora de...

Por lo general se usan transacciones a nivel base de datos y posteriormente se llaman estos a través de procedimientos a...

En este post, aprenderemos como conectar Visual Basic 6 con SQL Server, abrir una tabla, leer su contenido y mostrar est...

Lo que veremos en este post es la configuración del driver para PHP de SQL Server que ha creado Microsoft el cual permit...

Herramientas

Generador de Enlaces a Whatsapp