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 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 String 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 String 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/caracter 
 */
    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
 */
    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 String texto
 * @param int f tipo de fuente PLAIN | BOLD | ITALIC
 * @param int size tamaño de fuente
 * @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);
        setBackground(BG_COLOR);
        setSize(dimension);
        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 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 String texto a cifrar
 */
    public void cifrar(String text){
        //convierte el texto en un array 
        String[] tmpArray = text.split("");               
        String[] textArray = new String[tmpArray.length-1];
        System.arraycopy(tmpArray, 1, textArray, 0, tmpArray.length-1);
        //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
 */
    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

Descargar proyecto Cifrado PigPen

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

Libreria swing BlackTabbedPane

Libreria swing BlackTabbedPane

Continuación del tutorial [Personalizar JTabbedPane con Netbeans]. La clase BlackTabbedPaneUI que extendemos de BasicTab...

Capturar foto desde una webcam con Java Media Framework

Capturar foto desde una webcam con Java Media Framework

Como se vio en un post anterior (Capturar video de una webcam con JMF) la captura de un video desde una webcam utilizand...

JToggleButton y base de datos

JToggleButton y base de datos

En este tutorial veremos una forma de trabajar con el swing  JToggleButton y una base de datos para dar respuesta a una...

Método de la Regla Falsa o Regula Falsi

Método de la Regla Falsa o Regula Falsi

Este método, también conocido como método de interpolación lineal, es un método iterativo de resolución numérica de ecua...

SharedPreferences: Preferencias de Usuario

SharedPreferences: Preferencias de Usuario

En este post construiremos paso a paso un SharedPreferences más conocido en español como “Preferencias de Usuario...

Personalización de Componentes Swing Java I

Personalización de Componentes Swing Java I

Hace tiempo pidieron un video tutorial sobre como crear sus propios componentes swing java, lamentablemente debo decir q...

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

*

Comparte lo que sabes

Categorias

Últimas entradas

En este post construiremos paso a paso un SharedPreferences más conocido en español como “Preferencias de Usuario...

La Inteligencia Artificial (AI – Artificial Intelligence) estará presente en casi cada aspecto de nuestra vida en...

Una Interface Funcional es una interface que contiene uno y solo un método abstracto aunque puede contener métodos por d...

Un JSpinner es un componente swing de java con una caja de texto y un par de botones que nos permiten incrementar  y dec...

Android Bolivia

Bandera en Alto