package hudson.plugins.perforce; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.StringUtils; /** * @author stimmslocal */ public class PerforcePasswordEncryptor { private static final String keyString = "405kqo0gc20f9985142rj17779v4922568on29pwj92toqt884"; private static final String ENCRYPTION_PREFIX = "0f0kqlwa"; public PerforcePasswordEncryptor() { } public boolean appearsToBeAnEncryptedPassword(String toCheck) { return toCheck.startsWith(ENCRYPTION_PREFIX); } public String encryptString(String toEncrypt) { if (toEncrypt == null || toEncrypt.trim().length() == 0) return ""; SecretKey key = desKeyFromString(keyString); Cipher cipher = desCipherForModeWithKey(Cipher.ENCRYPT_MODE, key); byte[] encryptedtext = null; try { encryptedtext = cipher.doFinal(toEncrypt.getBytes()); } catch (IllegalBlockSizeException ibse) { System.err.println(ibse); } catch (BadPaddingException bpe) { System.err.println(bpe); } String encodedString = StringUtils.newStringUtf8(Base64.encodeBase64(encryptedtext, false)); return ENCRYPTION_PREFIX + encodedString; } public String decryptString(String toDecrypt) { if (toDecrypt == null || toDecrypt.length() == 0) return ""; SecretKey key = desKeyFromString(keyString); Cipher cipher = desCipherForModeWithKey(Cipher.DECRYPT_MODE, key); byte[] cleartext = null; try { // workaround bug with passwords which have a "+" in their BASE64 encoded form String processedToDecrypt = toDecrypt.replaceFirst(ENCRYPTION_PREFIX, "").replaceAll(" ", "+"); byte[] encryptedtext = Base64.decodeBase64(processedToDecrypt.getBytes()); cleartext = cipher.doFinal(encryptedtext); } catch (IllegalBlockSizeException ibse) { System.err.println(ibse); } catch (BadPaddingException bpe) { System.err.println(bpe); } return convertBytesToString(cleartext); } private static SecretKey desKeyFromString(String keystr) { try { byte[] keyBytes = keystr.getBytes("UTF8"); KeySpec keySpec = new DESKeySpec(keyBytes); SecretKeyFactory factory = SecretKeyFactory.getInstance("DES"); return factory.generateSecret(keySpec); } catch (UnsupportedEncodingException uee) { System.err.println(uee); } catch (InvalidKeyException ike) { System.err.println("Unable to create DES keyspec " + ike); } catch (NoSuchAlgorithmException nsal) { System.err.println(nsal); } catch (InvalidKeySpecException ikse) { System.err.print("Unable to generate secret key: " + ikse); } return null; } private static Cipher desCipherForModeWithKey(int mode, SecretKey key) { try { Cipher cipher = Cipher.getInstance("DES"); cipher.init(mode, key); return cipher; } catch (NoSuchAlgorithmException nsal) { System.err.println(nsal); } catch (NoSuchPaddingException nspe) { System.err.println(nspe); } catch (InvalidKeyException ike) { System.err.print("Unable to init cipher: " + ike); } return null; } private static String convertBytesToString(byte[] bytes) { if (bytes == null) return ""; StringBuffer stringBuffer = new StringBuffer(bytes.length); for (int i = 0; i < bytes.length; i++) { stringBuffer.append((char) bytes[i]); } return stringBuffer.toString(); } }