2011-05-31 3 views
1

Donc, je fais l'un des exercices de Princeton ici: http://www.cs.princeton.edu/courses/archive/fall10/cos126/assignments/lfsr.html et j'ai entièrement testé par classe LFSR avec les données qui ont été fournies, donc je suis sûr que je n'ai pas mal tourné là-bas. Cependant, ma classe PhotoMagic donne une photo cryptée de la pipe comme ci-dessous: Encrypted photo of the Pipe imageImpossible de comprendre le bug dans ce code

Ce n'est pas comment cela devrait apparaître. Une idée de l'endroit où mon code a mal tourné?

import java.awt.Color; 

public class PhotoMagic 
{ 
    private LFSR lfsr; 

public static void main(String args[]) 
{ 
    new PhotoMagic("src/pictures/shield.png","01101000010100010000",16); 

} 

public PhotoMagic(String imageName,String binaryPassword,int tap) 
{ 
    Picture pic = new Picture(imageName); 
    lfsr = new LFSR(binaryPassword,tap); 


    for (int x = 0; x < pic.width(); x++) 
    { 
     for (int y = 0; y < pic.height(); y++) 
     { 
      Color color = pic.get(x, y); 
      int red = color.getRed(); 
      int blue = color.getBlue(); 
      int green = color.getGreen(); 
      int transparency = color.getTransparency(); 
      int alpha = color.getAlpha(); 

      int newRed = xor(Integer.toBinaryString(red),paddedBitPattern(lfsr.generate(8))); 

      int newGreen = xor(Integer.toBinaryString(green),paddedBitPattern(lfsr.generate(8))); 

      int newBlue = xor(Integer.toBinaryString(blue),paddedBitPattern(lfsr.generate(8))); 

      Color newColor = new Color(newRed, newGreen, newBlue); 
      pic.set(x, y, newColor); 
     } 
    } 
    pic.show(); 
} 

/** 
* Pads bit pattern to the left with 0s if it is not 8 bits long 
* @param bitPattern 
* @return 
*/ 
public String paddedBitPattern(int bitPattern) 
{ 
    String tempBit = Integer.toBinaryString(bitPattern); 
    String newPattern = ""; 
    for(int i = 1; i < 9-tempBit.length(); i++) 
    { 
     newPattern += "0"; 
    } 
    newPattern += tempBit; 
    return newPattern; 
} 

/** 
* Performs the bitwise XOR 
* @param colorComponent 
* @param generatedBit 
* @return 
*/ 
public int xor(String colorComponent, String generatedBit) 
{ 
    String newColor = ""; 

    for(int i = 0; i < colorComponent.length(); i++) 
    { 
     if(colorComponent.charAt(i) != generatedBit.charAt(i)) 
     { 
      newColor += 1; 
     } 
     else 
     { 
      newColor += 0; 
     } 
    } 
    return Integer.valueOf(newColor,2); 
} 

}

+0

Vous pouvez simplement utiliser l'opérateur java xor directement sur les int et réduire votre taille de code de moitié. – toto2

Répondre

2

Vous devez remplir le résultat de Integer.toBinaryString() lors du calcul de newRed, newGreen et newBlue. Il peut ne pas avoir la longueur 8.

+0

+1 Un bon point.Si vous utilisiez des valeurs RGBA 16 bits, les octets supérieurs entiers ne seraient pas affectés. –

+0

merci! c'est en effet le bug! le programme fonctionne maintenant et les images peuvent être cryptées et décryptées selon l'affectation maintenant. – nope

2

La question est probable dans ce bloc de code

public String paddedBitPattern(int bitPattern) 
{ 
    String tempBit = Integer.toBinaryString(bitPattern); 
    String newPattern = ""; 
    for(int i = 1; i < 9-tempBit.length(); i++) 
    { 
     newPattern += "0"; 
    } 
    newPattern += tempBit; 
    return newPattern; 
} 

Notez que votre newPattern commence comme la chaîne de longueur zéro, puis vous ajoutez un texte zéro à ce pour chacun des bits dans bitPattern. Ensuite, vous ajoutez le bitPattern dans le newPattern et renvoyez le résultat. Cela conduit à un résultat 100% non aléatoire qui est une version à zéro remplissage du même bitPattern que vous venez de soumettre.

Donc, si l'entrée est

0010101101 

la sortie sera

00000000000010101101 

qui (lors de la suppression des zéros) est exactement l'entrée

0010101101 

Comme il n'y a plus de complexité, il ne gâche pas la capacité de l'esprit à la détection des contours: il est assez facile de voir le motif.

+0

désolé si ce n'était pas clair, mais les seuls arguments passés dans la méthode sont des nombres décimaux entre et inclus 0-255, il serait simplement l'équivalent binaire si elle était inférieure à 8 bits de long. donc 42 en binaire est 101010, mais la méthode le remplacera donc cela ressemblera à 00101010, ce qui permet à la méthode xor de le manipuler. donc le bug est autre chose. – nope

+0

@tomejuan, ok, donc c'est supposé être un peu à un convertisseur de chaîne seulement. Toutefois, une implémentation XOR ne peut pas fusionner au-delà du bit unique qu'elle contient. Cela signifie que si vous ne déplacez pas vos bits (via la rotation ou d'autres moyens), vous récupérez des données qui préservent les tendances dans les valeurs au-delà de la limite de la longueur de votre clé. Les images n'ont besoin que de quelques limites ici et là pour être reconnues, donc vous récupérerez quelque chose qui ressemble à une pipe intitulée "ce n'est pas une pipe". Si vous voulez étendre votre clé à 8x8 bits, tournez la clé après chaque passage à 'paddedBitPattern' d'un bit. –

+0

@tomejuan, en plus 8 bits est une très mauvaise limite pour un cryptage XOR sur une image. Il est utilisé parce qu'il est efficace sur le plan informatique et facile à programmer; mais, les limites de RGBA a 8 bits pour Rouge, Vert, Bleu et Alpha. Ainsi, chaque bit est seulement modifié en couleur, indépendamment du pixel qui se trouve à côté de lui. Les humains peuvent facilement reconnaître un arbre, même s'il est bleu. Le changement de couleur ne va pas rendre votre image moins reconnaissable. –

0

J'ai modifié comme suit. Ça a marché. Pourquoi avez-vous tout transformé en `String`s?

int newRed = xor(paddedBitPattern(red),paddedBitPattern(lfsr.generate(8)));  
int newGreen = xor(paddedBitPattern(green),paddedBitPattern(lfsr.generate(8))); 
int newBlue = xor(paddedBitPattern(blue),paddedBitPattern(lfsr.generate(8)));