/* * Copyright (C) 2011 Andrew E. Bruno <aeb@qnot.org> * * This file is part of passtab. * * passtab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * passtab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with passtab. If not, see <http://www.gnu.org/licenses/>. */ package org.qnot.passtab; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import org.apache.commons.math.random.RandomDataImpl; import com.google.gson.Gson; /** * Tabula Recta class * * @author Andrew E. Bruno <aeb@qnot.org> */ public class TabulaRecta { private String[][] tabulaRecta; private Alphabet headerAlphabet; private Alphabet dataAlphabet; public TabulaRecta(Alphabet headerAlphabet, Alphabet dataAlphabet) { this.headerAlphabet = headerAlphabet; this.dataAlphabet = dataAlphabet; this.tabulaRecta = new String[headerAlphabet.size()][headerAlphabet .size()]; } public static TabulaRecta fromJSON(String json) { Gson gson = new Gson(); return gson.fromJson(json, TabulaRecta.class); } public String get(int row, int col) { return this.tabulaRecta[row][col]; } public Alphabet getHeader() { return this.headerAlphabet; } public Alphabet getDataAlphabet() { return this.dataAlphabet; } public String[][] getRawData() { return this.tabulaRecta; } public int rows() { return this.tabulaRecta.length; } public int cols() { return this.tabulaRecta.length; } public String[][] asStringArray() { String[][] array = new String[this.rows() + 1][this.cols() + 1]; array[0][0] = " "; for (int i = 0; i < this.cols(); i++) { array[0][i + 1] = this.headerAlphabet.get(i); } for (int i = 0; i < this.rows(); i++) { array[i + 1][0] = this.headerAlphabet.get(i); for (int j = 0; j < this.cols(); j++) { array[i + 1][j + 1] = this.get(i, j); } } return array; } public String getPassword(int startRow, int startCol, Sequence sequence) { return this.getPassword(startRow, startCol, sequence, false, 0, null); } public String getPassword(int startRow, int startCol, Sequence sequence, Direction[] directionPriority) { return this.getPassword(startRow, startCol, sequence, false, 0, directionPriority); } public String getPassword(int startRow, int startCol, Sequence sequence, boolean skipStart, int skipInterval, Direction[] directionPriority) { String pass = ""; skipInterval++; int reads = skipInterval; if (!skipStart) { pass += this.get(startRow, startCol); } Position pos = new Position(startRow, startCol); Direction dir = null; for (SequenceItem i : sequence.getItemList()) { dir = i.getDirection(); int len = i.getLength(); boolean skip = false; if (len < 0) { skip = true; len = Math.abs(len); } for (int x = 0; x < (len*skipInterval); x++) { pos.move(dir); if (pos.isOutOfBounds(this.rows() - 1, this.cols() - 1) && directionPriority != null) { pos.backup(); for (Direction dp : directionPriority) { pos.move(dp); if (pos.isOutOfBounds(this.rows() - 1, this.cols() - 1)) { pos.backup(); } else { dir = dp; break; } } } if (pos.isOutOfBounds(this.rows() - 1, this.cols() - 1)) { pos.setWithinBounds(this.rows() - 1, this.cols() - 1); } reads--; if (!skip && reads == 0) { pass += this.get(pos.getRow(), pos.getCol()); } if(reads == 0) reads = skipInterval; } } return pass; } public void generate() { RandomDataImpl rand = new RandomDataImpl(); try { rand.setSecureAlgorithm("SHA1PRNG", "SUN"); } catch (NoSuchProviderException e) { throw new RuntimeException("Failed to set secure provider", e); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("Failed to set secure algorithm", e); } for (int i = 0; i < this.headerAlphabet.size(); i++) { tabulaRecta[i] = generateRow(i, rand); } } private String[] generateRow(int rowIndex, RandomDataImpl rand) { String[] row = new String[this.headerAlphabet.size()]; for (int i = 0; i < this.headerAlphabet.size(); i++) { int index = rand.nextSecureInt(0, (this.dataAlphabet.size() - 1)); row[i] = this.dataAlphabet.get(index); } return row; } }