blob: 99022e052e03313d312bb26abca4eeb454b8d63b [file] [log] [blame]
/*****************************************************************************
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License Version
* 1.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is available at http://www.sun.com/
* The Original Code is the CVS Client Library.
* The Initial Developer of the Original Code is Robert Greig.
* Portions created by Robert Greig are Copyright (C) 2000.
* All Rights Reserved.
* Contributor(s): Robert Greig.
*****************************************************************************/
package org.netbeans.lib.cvsclient.connection;
/**
* Scrambles text (the password) using the standard scheme described in the
* CVS protocol version 1.10. This encoding is trivial and should not be
* used for security, but rather as a mechanism for avoiding inadvertant
* compromise.
* @author Robert Greig
*/
public final class PServerPasswordScrambler {
// Static =================================================================
private static final PServerPasswordScrambler instance = new PServerPasswordScrambler();
/**
* Get an instance of the standard scrambler
*/
public static PServerPasswordScrambler getInstance() {
return instance;
}
// Fields =================================================================
private final int[] shifts;
// Setup ==================================================================
/**
* Do not instantiate the scrambler directly. Use the getInstance() method
*/
private PServerPasswordScrambler() {
this.shifts = new int[256];
int i;
for (i = 0; i < 32; ++i) {
shifts[i] = i;
}
shifts[i++] = 114;
shifts[i++] = 120;
shifts[i++] = 53;
shifts[i++] = 79;
shifts[i++] = 96;
shifts[i++] = 109;
shifts[i++] = 72;
shifts[i++] = 108;
shifts[i++] = 70;
shifts[i++] = 64;
shifts[i++] = 76;
shifts[i++] = 67;
shifts[i++] = 116;
shifts[i++] = 74;
shifts[i++] = 68;
shifts[i++] = 87;
shifts[i++] = 111;
shifts[i++] = 52;
shifts[i++] = 75;
shifts[i++] = 119;
shifts[i++] = 49;
shifts[i++] = 34;
shifts[i++] = 82;
shifts[i++] = 81;
shifts[i++] = 95;
shifts[i++] = 65;
shifts[i++] = 112;
shifts[i++] = 86;
shifts[i++] = 118;
shifts[i++] = 110;
shifts[i++] = 122;
shifts[i++] = 105;
shifts[i++] = 41;
shifts[i++] = 57;
shifts[i++] = 83;
shifts[i++] = 43;
shifts[i++] = 46;
shifts[i++] = 102;
shifts[i++] = 40;
shifts[i++] = 89;
shifts[i++] = 38;
shifts[i++] = 103;
shifts[i++] = 45;
shifts[i++] = 50;
shifts[i++] = 42;
shifts[i++] = 123;
shifts[i++] = 91;
shifts[i++] = 35;
shifts[i++] = 125;
shifts[i++] = 55;
shifts[i++] = 54;
shifts[i++] = 66;
shifts[i++] = 124;
shifts[i++] = 126;
shifts[i++] = 59;
shifts[i++] = 47;
shifts[i++] = 92;
shifts[i++] = 71;
shifts[i++] = 115;
shifts[i++] = 78;
shifts[i++] = 88;
shifts[i++] = 107;
shifts[i++] = 106;
shifts[i++] = 56;
shifts[i++] = 36;
shifts[i++] = 121;
shifts[i++] = 117;
shifts[i++] = 104;
shifts[i++] = 101;
shifts[i++] = 100;
shifts[i++] = 69;
shifts[i++] = 73;
shifts[i++] = 99;
shifts[i++] = 63;
shifts[i++] = 94;
shifts[i++] = 93;
shifts[i++] = 39;
shifts[i++] = 37;
shifts[i++] = 61;
shifts[i++] = 48;
shifts[i++] = 58;
shifts[i++] = 113;
shifts[i++] = 32;
shifts[i++] = 90;
shifts[i++] = 44;
shifts[i++] = 98;
shifts[i++] = 60;
shifts[i++] = 51;
shifts[i++] = 33;
shifts[i++] = 97;
shifts[i++] = 62;
shifts[i++] = 77;
shifts[i++] = 84;
shifts[i++] = 80;
shifts[i++] = 85;
shifts[i++] = 223;
shifts[i++] = 225;
shifts[i++] = 216;
shifts[i++] = 187;
shifts[i++] = 166;
shifts[i++] = 229;
shifts[i++] = 189;
shifts[i++] = 222;
shifts[i++] = 188;
shifts[i++] = 141;
shifts[i++] = 249;
shifts[i++] = 148;
shifts[i++] = 200;
shifts[i++] = 184;
shifts[i++] = 136;
shifts[i++] = 248;
shifts[i++] = 190;
shifts[i++] = 199;
shifts[i++] = 170;
shifts[i++] = 181;
shifts[i++] = 204;
shifts[i++] = 138;
shifts[i++] = 232;
shifts[i++] = 218;
shifts[i++] = 183;
shifts[i++] = 255;
shifts[i++] = 234;
shifts[i++] = 220;
shifts[i++] = 247;
shifts[i++] = 213;
shifts[i++] = 203;
shifts[i++] = 226;
shifts[i++] = 193;
shifts[i++] = 174;
shifts[i++] = 172;
shifts[i++] = 228;
shifts[i++] = 252;
shifts[i++] = 217;
shifts[i++] = 201;
shifts[i++] = 131;
shifts[i++] = 230;
shifts[i++] = 197;
shifts[i++] = 211;
shifts[i++] = 145;
shifts[i++] = 238;
shifts[i++] = 161;
shifts[i++] = 179;
shifts[i++] = 160;
shifts[i++] = 212;
shifts[i++] = 207;
shifts[i++] = 221;
shifts[i++] = 254;
shifts[i++] = 173;
shifts[i++] = 202;
shifts[i++] = 146;
shifts[i++] = 224;
shifts[i++] = 151;
shifts[i++] = 140;
shifts[i++] = 196;
shifts[i++] = 205;
shifts[i++] = 130;
shifts[i++] = 135;
shifts[i++] = 133;
shifts[i++] = 143;
shifts[i++] = 246;
shifts[i++] = 192;
shifts[i++] = 159;
shifts[i++] = 244;
shifts[i++] = 239;
shifts[i++] = 185;
shifts[i++] = 168;
shifts[i++] = 215;
shifts[i++] = 144;
shifts[i++] = 139;
shifts[i++] = 165;
shifts[i++] = 180;
shifts[i++] = 157;
shifts[i++] = 147;
shifts[i++] = 186;
shifts[i++] = 214;
shifts[i++] = 176;
shifts[i++] = 227;
shifts[i++] = 231;
shifts[i++] = 219;
shifts[i++] = 169;
shifts[i++] = 175;
shifts[i++] = 156;
shifts[i++] = 206;
shifts[i++] = 198;
shifts[i++] = 129;
shifts[i++] = 164;
shifts[i++] = 150;
shifts[i++] = 210;
shifts[i++] = 154;
shifts[i++] = 177;
shifts[i++] = 134;
shifts[i++] = 127;
shifts[i++] = 182;
shifts[i++] = 128;
shifts[i++] = 158;
shifts[i++] = 208;
shifts[i++] = 162;
shifts[i++] = 132;
shifts[i++] = 167;
shifts[i++] = 209;
shifts[i++] = 149;
shifts[i++] = 241;
shifts[i++] = 153;
shifts[i++] = 251;
shifts[i++] = 237;
shifts[i++] = 236;
shifts[i++] = 171;
shifts[i++] = 195;
shifts[i++] = 243;
shifts[i++] = 233;
shifts[i++] = 253;
shifts[i++] = 240;
shifts[i++] = 194;
shifts[i++] = 250;
shifts[i++] = 191;
shifts[i++] = 155;
shifts[i++] = 142;
shifts[i++] = 137;
shifts[i++] = 245;
shifts[i++] = 235;
shifts[i++] = 163;
shifts[i++] = 242;
shifts[i++] = 178;
shifts[i] = 152;
}
/**
* Scramble text, turning it into a String of scrambled data
* @return a String of scrambled data
*/
@SuppressWarnings({"HardCodedStringLiteral"})
public String scramble(String text) {
final StringBuffer buffer = new StringBuffer("A");
if (text != null) {
for (int i = 0; i < text.length(); ++i) {
final char chr = text.charAt(i);
final byte scrambledChr = (byte)(shifts[(int)chr & 255] & 255);
buffer.append((char)scrambledChr);
}
}
return buffer.toString();
}
@SuppressWarnings({"HardCodedStringLiteral"})
public String unscramble(String scrambledText) {
if (scrambledText == null) {
return null;
}
if (!scrambledText.startsWith("A")) {
throw new IllegalArgumentException("Unknown scramble method '" + scrambledText + "'");
}
final StringBuffer buffer = new StringBuffer(scrambledText.length() - 1);
for (int i = 1; i < scrambledText.length(); i++) {
final char scrambledChr = scrambledText.charAt(i);
final char chr = unscramble(scrambledChr);
buffer.append(chr);
}
return buffer.toString();
}
// Utils ==================================================================
private char unscramble(char scrambledChr) {
final int scrambledInt = (int)(scrambledChr & 255);
for (int i = 0; i < shifts.length; i++) {
if (shifts[i] == scrambledInt) {
return (char)i;
}
}
throw new IllegalArgumentException("Invalid scrambled character 0x" + Integer.toHexString(scrambledInt));
}
}