Aprende Java Aprende Php Aprende C++ Aprende HTML 5 Aprende JavaScript Aprende JSON Aprende MySQL Aprende SQLServer Aprende Visual Basic 6 Aprende PostgreSQL Aprende SQLite Aprende Redis Aprende Kotlin Aprende XML Aprende Linux VSC Aprende Wordpress Aprende Laravel Aprende VueJS Aprende JQuery Aprende Bootstrap Aprende Netbeans Aprende Android
Sigueme en Facebook Sigueme en Twitter Sigueme en Instagram Sigueme en Youtube Sigueme en TikTok Sigueme en Whatsapp
Home / Java / Cifrado francmasón PigPen

Cifrado francmasón PigPen

Por 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 Game Of Thrones:

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

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

Descarga el codigo desde MEGA

Enjoy!!!

Tags

Artículos similares

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[...]

Uso y creación de archivos 9-Patch

Antes de la aparición de los celulares inteligentes y de las grandes mejoras tecnológicas que trajeron con ellas, las ap[...]

JSCRUM .:. Gestor de Proyectos

¿Qué es SCRUM? SCRUM es un modelo de referencia que define un conjunto de prácticas y roles, y que puede tomarse como pu[...]

Tangram: El rompecabezas chino

El Tangram es un juego chino muy antiguo, esta compuesto por 7 piezas: un paralelogramo (romboide), un cuadrado y 5 triá[...]

Yachaywasi – Crea exámenes tipo test para android

Yachaywasi versión 3.1 es una aplicación para android que te permite crear, editar y realizar exámenes tipo test cómodam[...]

Abre una aplicación swing java desde el navegador de forma segura

Los mejores días del marco de java swing se han ido. Las aplicaciones de escritorio perdieron popularidad y todo está fo[...]