/***************************************************************************** * 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)); } }