/*
* JBoss, Home of Professional Open Source.
* Copyright 2014 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wildfly.security.password.impl;
import static org.wildfly.common.math.HashMath.multiHashOrdered;
import static org.wildfly.security._private.ElytronMessages.log;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
import org.wildfly.security.password.interfaces.UnixDESCryptPassword;
import org.wildfly.security.password.spec.ClearPasswordSpec;
import org.wildfly.security.password.spec.SaltedHashPasswordSpec;
import org.wildfly.security.password.spec.SaltedPasswordAlgorithmSpec;
/**
* @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
*/
class UnixDESCryptPasswordImpl extends AbstractPasswordImpl implements UnixDESCryptPassword {
private static final long serialVersionUID = -1531925386776476431L;
private final short salt;
private final byte[] hash;
UnixDESCryptPasswordImpl(final short salt, final byte[] hash) throws InvalidKeyException {
this.salt = salt;
if (hash == null || hash.length != 8) {
throw log.invalidKeyDesCryptPasswordHashMustBeBytes(8);
}
this.hash = hash;
}
UnixDESCryptPasswordImpl(final byte[] saltBytes, final byte[] hash) throws InvalidParameterSpecException, InvalidKeyException {
this(saltFromBytes(saltBytes), hash);
}
UnixDESCryptPasswordImpl(final byte[] saltBytes, final char[] passwordChars) throws InvalidParameterSpecException, InvalidKeyException {
this(saltFromBytes(saltBytes), passwordChars);
}
UnixDESCryptPasswordImpl(final SaltedHashPasswordSpec spec) throws InvalidKeySpecException, InvalidParameterSpecException, InvalidKeyException {
this(spec.getSalt(), spec.getHash().clone());
}
UnixDESCryptPasswordImpl(final ClearPasswordSpec spec) throws InvalidKeySpecException, InvalidKeyException {
this((short) (ThreadLocalRandom.current().nextInt() & 0xfff), spec.getEncodedPassword());
}
UnixDESCryptPasswordImpl(final char[] passwordChars) throws InvalidKeyException {
this((short) (ThreadLocalRandom.current().nextInt() & 0xfff), passwordChars);
}
UnixDESCryptPasswordImpl(final char[] passwordChars, SaltedPasswordAlgorithmSpec algorithmSpec) throws InvalidParameterSpecException, InvalidKeyException {
this(algorithmSpec.getSalt(), passwordChars);
}
UnixDESCryptPasswordImpl(final UnixDESCryptPassword password) throws InvalidKeyException {
this(password.getSalt(), password.getHash());
}
UnixDESCryptPasswordImpl(final short salt, final char[] passwordChars) throws InvalidKeyException {
this(salt, generateHash(salt, passwordChars));
}
private static short saltFromBytes(final byte[] saltBytes) throws InvalidParameterSpecException {
if (saltBytes.length != 2) {
throw log.invalidParameterSpecSaltMustBeBytesBits(2, 12);
}
return (short) ((saltBytes[0] & 0x0f) << 8 | saltBytes[1] & 0xff);
}
<S extends KeySpec> S getKeySpec(final Class<S> keySpecType) throws InvalidKeySpecException {
if (keySpecType.isAssignableFrom(SaltedHashPasswordSpec.class)) {
return keySpecType.cast(new SaltedHashPasswordSpec(hash.clone(), ByteBuffer.allocate(2).putShort(this.salt).array()));
}
throw new InvalidKeySpecException();
}
boolean verify(final char[] guess) throws InvalidKeyException {
return Arrays.equals(hash, generateHash(salt, guess));
}
<T extends KeySpec> boolean convertibleTo(final Class<T> keySpecType) {
return keySpecType.isAssignableFrom(SaltedHashPasswordSpec.class);
}
public String getAlgorithm() {
return UnixDESCryptPassword.ALGORITHM_CRYPT_DES;
}
public short getSalt() {
return salt;
}
public byte[] getHash() {
return hash.clone();
}
private static byte[] generateHash(final short salt, final char[] password) {
// get bytes
final byte[] bytes1 = getNormalizedPasswordBytes(password);
return crypt(bytes1, salt);
}
// Much of the following code was copied from Apache commons-codec; at some point we may consider just adding
// a dependency?
private static final boolean[] SHIFT2 = { false, false, true, true, true, true, true, true, false, true, true,
true, true, true, true, false };
private static final int[][] SKB = {
{ 0, 16, 0x20000000, 0x20000010, 0x10000, 0x10010, 0x20010000, 0x20010010, 2048, 2064, 0x20000800,
0x20000810, 0x10800, 0x10810, 0x20010800, 0x20010810, 32, 48, 0x20000020, 0x20000030, 0x10020,
0x10030, 0x20010020, 0x20010030, 2080, 2096, 0x20000820, 0x20000830, 0x10820, 0x10830, 0x20010820,
0x20010830, 0x80000, 0x80010, 0x20080000, 0x20080010, 0x90000, 0x90010, 0x20090000, 0x20090010,
0x80800, 0x80810, 0x20080800, 0x20080810, 0x90800, 0x90810, 0x20090800, 0x20090810, 0x80020,
0x80030, 0x20080020, 0x20080030, 0x90020, 0x90030, 0x20090020, 0x20090030, 0x80820, 0x80830,
0x20080820, 0x20080830, 0x90820, 0x90830, 0x20090820, 0x20090830 },
{ 0, 0x2000000, 8192, 0x2002000, 0x200000, 0x2200000, 0x202000, 0x2202000, 4, 0x2000004, 8196, 0x2002004,
0x200004, 0x2200004, 0x202004, 0x2202004, 1024, 0x2000400, 9216, 0x2002400, 0x200400, 0x2200400,
0x202400, 0x2202400, 1028, 0x2000404, 9220, 0x2002404, 0x200404, 0x2200404, 0x202404, 0x2202404,
0x10000000, 0x12000000, 0x10002000, 0x12002000, 0x10200000, 0x12200000, 0x10202000, 0x12202000,
0x10000004, 0x12000004, 0x10002004, 0x12002004, 0x10200004, 0x12200004, 0x10202004, 0x12202004,
0x10000400, 0x12000400, 0x10002400, 0x12002400, 0x10200400, 0x12200400, 0x10202400, 0x12202400,
0x10000404, 0x12000404, 0x10002404, 0x12002404, 0x10200404, 0x12200404, 0x10202404, 0x12202404 },
{ 0, 1, 0x40000, 0x40001, 0x1000000, 0x1000001, 0x1040000, 0x1040001, 2, 3, 0x40002, 0x40003, 0x1000002,
0x1000003, 0x1040002, 0x1040003, 512, 513, 0x40200, 0x40201, 0x1000200, 0x1000201, 0x1040200,
0x1040201, 514, 515, 0x40202, 0x40203, 0x1000202, 0x1000203, 0x1040202, 0x1040203, 0x8000000,
0x8000001, 0x8040000, 0x8040001, 0x9000000, 0x9000001, 0x9040000, 0x9040001, 0x8000002, 0x8000003,
0x8040002, 0x8040003, 0x9000002, 0x9000003, 0x9040002, 0x9040003, 0x8000200, 0x8000201, 0x8040200,
0x8040201, 0x9000200, 0x9000201, 0x9040200, 0x9040201, 0x8000202, 0x8000203, 0x8040202, 0x8040203,
0x9000202, 0x9000203, 0x9040202, 0x9040203 },
{ 0, 0x100000, 256, 0x100100, 8, 0x100008, 264, 0x100108, 4096, 0x101000, 4352, 0x101100, 4104, 0x101008,
4360, 0x101108, 0x4000000, 0x4100000, 0x4000100, 0x4100100, 0x4000008, 0x4100008, 0x4000108,
0x4100108, 0x4001000, 0x4101000, 0x4001100, 0x4101100, 0x4001008, 0x4101008, 0x4001108, 0x4101108,
0x20000, 0x120000, 0x20100, 0x120100, 0x20008, 0x120008, 0x20108, 0x120108, 0x21000, 0x121000,
0x21100, 0x121100, 0x21008, 0x121008, 0x21108, 0x121108, 0x4020000, 0x4120000, 0x4020100,
0x4120100, 0x4020008, 0x4120008, 0x4020108, 0x4120108, 0x4021000, 0x4121000, 0x4021100, 0x4121100,
0x4021008, 0x4121008, 0x4021108, 0x4121108 },
{ 0, 0x10000000, 0x10000, 0x10010000, 4, 0x10000004, 0x10004, 0x10010004, 0x20000000, 0x30000000,
0x20010000, 0x30010000, 0x20000004, 0x30000004, 0x20010004, 0x30010004, 0x100000, 0x10100000,
0x110000, 0x10110000, 0x100004, 0x10100004, 0x110004, 0x10110004, 0x20100000, 0x30100000,
0x20110000, 0x30110000, 0x20100004, 0x30100004, 0x20110004, 0x30110004, 4096, 0x10001000, 0x11000,
0x10011000, 4100, 0x10001004, 0x11004, 0x10011004, 0x20001000, 0x30001000, 0x20011000, 0x30011000,
0x20001004, 0x30001004, 0x20011004, 0x30011004, 0x101000, 0x10101000, 0x111000, 0x10111000,
0x101004, 0x10101004, 0x111004, 0x10111004, 0x20101000, 0x30101000, 0x20111000, 0x30111000,
0x20101004, 0x30101004, 0x20111004, 0x30111004 },
{ 0, 0x8000000, 8, 0x8000008, 1024, 0x8000400, 1032, 0x8000408, 0x20000, 0x8020000, 0x20008, 0x8020008,
0x20400, 0x8020400, 0x20408, 0x8020408, 1, 0x8000001, 9, 0x8000009, 1025, 0x8000401, 1033,
0x8000409, 0x20001, 0x8020001, 0x20009, 0x8020009, 0x20401, 0x8020401, 0x20409, 0x8020409,
0x2000000, 0xa000000, 0x2000008, 0xa000008, 0x2000400, 0xa000400, 0x2000408, 0xa000408, 0x2020000,
0xa020000, 0x2020008, 0xa020008, 0x2020400, 0xa020400, 0x2020408, 0xa020408, 0x2000001, 0xa000001,
0x2000009, 0xa000009, 0x2000401, 0xa000401, 0x2000409, 0xa000409, 0x2020001, 0xa020001, 0x2020009,
0xa020009, 0x2020401, 0xa020401, 0x2020409, 0xa020409 },
{ 0, 256, 0x80000, 0x80100, 0x1000000, 0x1000100, 0x1080000, 0x1080100, 16, 272, 0x80010, 0x80110,
0x1000010, 0x1000110, 0x1080010, 0x1080110, 0x200000, 0x200100, 0x280000, 0x280100, 0x1200000,
0x1200100, 0x1280000, 0x1280100, 0x200010, 0x200110, 0x280010, 0x280110, 0x1200010, 0x1200110,
0x1280010, 0x1280110, 512, 768, 0x80200, 0x80300, 0x1000200, 0x1000300, 0x1080200, 0x1080300, 528,
784, 0x80210, 0x80310, 0x1000210, 0x1000310, 0x1080210, 0x1080310, 0x200200, 0x200300, 0x280200,
0x280300, 0x1200200, 0x1200300, 0x1280200, 0x1280300, 0x200210, 0x200310, 0x280210, 0x280310,
0x1200210, 0x1200310, 0x1280210, 0x1280310 },
{ 0, 0x4000000, 0x40000, 0x4040000, 2, 0x4000002, 0x40002, 0x4040002, 8192, 0x4002000, 0x42000, 0x4042000,
8194, 0x4002002, 0x42002, 0x4042002, 32, 0x4000020, 0x40020, 0x4040020, 34, 0x4000022, 0x40022,
0x4040022, 8224, 0x4002020, 0x42020, 0x4042020, 8226, 0x4002022, 0x42022, 0x4042022, 2048,
0x4000800, 0x40800, 0x4040800, 2050, 0x4000802, 0x40802, 0x4040802, 10240, 0x4002800, 0x42800,
0x4042800, 10242, 0x4002802, 0x42802, 0x4042802, 2080, 0x4000820, 0x40820, 0x4040820, 2082,
0x4000822, 0x40822, 0x4040822, 10272, 0x4002820, 0x42820, 0x4042820, 10274, 0x4002822, 0x42822,
0x4042822 } };
private static final int[][] SP_TRANS = {
{ 0x820200, 0x20000, 0x80800000, 0x80820200, 0x800000, 0x80020200, 0x80020000, 0x80800000, 0x80020200,
0x820200, 0x820000, 0x80000200, 0x80800200, 0x800000, 0, 0x80020000, 0x20000, 0x80000000,
0x800200, 0x20200, 0x80820200, 0x820000, 0x80000200, 0x800200, 0x80000000, 512, 0x20200,
0x80820000, 512, 0x80800200, 0x80820000, 0, 0, 0x80820200, 0x800200, 0x80020000, 0x820200,
0x20000, 0x80000200, 0x800200, 0x80820000, 512, 0x20200, 0x80800000, 0x80020200, 0x80000000,
0x80800000, 0x820000, 0x80820200, 0x20200, 0x820000, 0x80800200, 0x800000, 0x80000200, 0x80020000,
0, 0x20000, 0x800000, 0x80800200, 0x820200, 0x80000000, 0x80820000, 512, 0x80020200 },
{ 0x10042004, 0, 0x42000, 0x10040000, 0x10000004, 8196, 0x10002000, 0x42000, 8192, 0x10040004, 4,
0x10002000, 0x40004, 0x10042000, 0x10040000, 4, 0x40000, 0x10002004, 0x10040004, 8192, 0x42004,
0x10000000, 0, 0x40004, 0x10002004, 0x42004, 0x10042000, 0x10000004, 0x10000000, 0x40000, 8196,
0x10042004, 0x40004, 0x10042000, 0x10002000, 0x42004, 0x10042004, 0x40004, 0x10000004, 0,
0x10000000, 8196, 0x40000, 0x10040004, 8192, 0x10000000, 0x42004, 0x10002004, 0x10042000, 8192, 0,
0x10000004, 4, 0x10042004, 0x42000, 0x10040000, 0x10040004, 0x40000, 8196, 0x10002000, 0x10002004,
4, 0x10040000, 0x42000 },
{ 0x41000000, 0x1010040, 64, 0x41000040, 0x40010000, 0x1000000, 0x41000040, 0x10040, 0x1000040, 0x10000,
0x1010000, 0x40000000, 0x41010040, 0x40000040, 0x40000000, 0x41010000, 0, 0x40010000, 0x1010040,
64, 0x40000040, 0x41010040, 0x10000, 0x41000000, 0x41010000, 0x1000040, 0x40010040, 0x1010000,
0x10040, 0, 0x1000000, 0x40010040, 0x1010040, 64, 0x40000000, 0x10000, 0x40000040, 0x40010000,
0x1010000, 0x41000040, 0, 0x1010040, 0x10040, 0x41010000, 0x40010000, 0x1000000, 0x41010040,
0x40000000, 0x40010040, 0x41000000, 0x1000000, 0x41010040, 0x10000, 0x1000040, 0x41000040,
0x10040, 0x1000040, 0, 0x41010000, 0x40000040, 0x41000000, 0x40010040, 64, 0x1010000 },
{ 0x100402, 0x4000400, 2, 0x4100402, 0, 0x4100000, 0x4000402, 0x100002, 0x4100400, 0x4000002, 0x4000000,
1026, 0x4000002, 0x100402, 0x100000, 0x4000000, 0x4100002, 0x100400, 1024, 2, 0x100400, 0x4000402,
0x4100000, 1024, 1026, 0, 0x100002, 0x4100400, 0x4000400, 0x4100002, 0x4100402, 0x100000,
0x4100002, 1026, 0x100000, 0x4000002, 0x100400, 0x4000400, 2, 0x4100000, 0x4000402, 0, 1024,
0x100002, 0, 0x4100002, 0x4100400, 1024, 0x4000000, 0x4100402, 0x100402, 0x100000, 0x4100402, 2,
0x4000400, 0x100402, 0x100002, 0x100400, 0x4100000, 0x4000402, 1026, 0x4000000, 0x4000002,
0x4100400 },
{ 0x2000000, 16384, 256, 0x2004108, 0x2004008, 0x2000100, 16648, 0x2004000, 16384, 8, 0x2000008, 16640,
0x2000108, 0x2004008, 0x2004100, 0, 16640, 0x2000000, 16392, 264, 0x2000100, 16648, 0, 0x2000008,
8, 0x2000108, 0x2004108, 16392, 0x2004000, 256, 264, 0x2004100, 0x2004100, 0x2000108, 16392,
0x2004000, 16384, 8, 0x2000008, 0x2000100, 0x2000000, 16640, 0x2004108, 0, 16648, 0x2000000, 256,
16392, 0x2000108, 256, 0, 0x2004108, 0x2004008, 0x2004100, 264, 16384, 16640, 0x2004008,
0x2000100, 264, 8, 16648, 0x2004000, 0x2000008 },
{ 0x20000010, 0x80010, 0, 0x20080800, 0x80010, 2048, 0x20000810, 0x80000, 2064, 0x20080810, 0x80800,
0x20000000, 0x20000800, 0x20000010, 0x20080000, 0x80810, 0x80000, 0x20000810, 0x20080010, 0, 2048,
16, 0x20080800, 0x20080010, 0x20080810, 0x20080000, 0x20000000, 2064, 16, 0x80800, 0x80810,
0x20000800, 2064, 0x20000000, 0x20000800, 0x80810, 0x20080800, 0x80010, 0, 0x20000800, 0x20000000,
2048, 0x20080010, 0x80000, 0x80010, 0x20080810, 0x80800, 16, 0x20080810, 0x80800, 0x80000,
0x20000810, 0x20000010, 0x20080000, 0x80810, 0, 2048, 0x20000010, 0x20000810, 0x20080800,
0x20080000, 2064, 16, 0x20080010 },
{ 4096, 128, 0x400080, 0x400001, 0x401081, 4097, 4224, 0, 0x400000, 0x400081, 129, 0x401000, 1, 0x401080,
0x401000, 129, 0x400081, 4096, 4097, 0x401081, 0, 0x400080, 0x400001, 4224, 0x401001, 4225,
0x401080, 1, 4225, 0x401001, 128, 0x400000, 4225, 0x401000, 0x401001, 129, 4096, 128, 0x400000,
0x401001, 0x400081, 4225, 4224, 0, 128, 0x400001, 1, 0x400080, 0, 0x400081, 0x400080, 4224, 129,
4096, 0x401081, 0x400000, 0x401080, 1, 4097, 0x401081, 0x400001, 0x401080, 0x401000, 4097 },
{ 0x8200020, 0x8208000, 32800, 0, 0x8008000, 0x200020, 0x8200000, 0x8208020, 32, 0x8000000, 0x208000,
32800, 0x208020, 0x8008020, 0x8000020, 0x8200000, 32768, 0x208020, 0x200020, 0x8008000, 0x8208020,
0x8000020, 0, 0x208000, 0x8000000, 0x200000, 0x8008020, 0x8200020, 0x200000, 32768, 0x8208000, 32,
0x200000, 32768, 0x8000020, 0x8208020, 32800, 0x8000000, 0, 0x208000, 0x8200020, 0x8008020,
0x8008000, 0x200020, 0x8208000, 32, 0x200020, 0x8008000, 0x8208020, 0x200000, 0x8200000,
0x8000020, 0x208000, 32800, 0x8008020, 0x8200000, 32, 0x8208000, 0x208020, 0, 0x8000000,
0x8200020, 32768, 0x208020 } };
private static byte[] crypt(final byte[] original, short salt) {
final int eSwap0 = salt >> 0 & 0x3F;
final int eSwap1 = (salt >> 6 & 0x3F) << 4;
final byte[] hash = new byte[8];
final byte[] key = new byte[8];
for (int i = 0; i < key.length; i++) {
key[i] = 0;
}
for (int i = 0; i < key.length && i < original.length; i++) {
final int iChar = original[i];
key[i] = (byte) (iChar << 1);
}
final int[] schedule = desSetKey(key);
final int[] out = body(schedule, eSwap0, eSwap1);
intToFourBytes(out[0], hash, 0);
intToFourBytes(out[1], hash, 4);
return hash;
}
private static int[] body(final int[] schedule, final int eSwap0, final int eSwap1) {
int left = 0;
int right = 0;
int t;
for (int j = 0; j < 25; j++) {
for (int i = 0; i < 32; i += 4) {
left = dEncrypt(left, right, i, eSwap0, eSwap1, schedule);
right = dEncrypt(right, left, i + 2, eSwap0, eSwap1, schedule);
}
t = left;
left = right;
right = t;
}
t = right;
right = left >>> 1 | left << 31;
left = t >>> 1 | t << 31;
final int[] results = new int[2];
permOp(right, left, 1, 0x55555555, results);
right = results[0];
left = results[1];
permOp(left, right, 8, 0xff00ff, results);
left = results[0];
right = results[1];
permOp(right, left, 2, 0x33333333, results);
right = results[0];
left = results[1];
permOp(left, right, 16, 65535, results);
left = results[0];
right = results[1];
permOp(right, left, 4, 0xf0f0f0f, results);
right = results[0];
left = results[1];
final int[] out = new int[2];
out[0] = left;
out[1] = right;
return out;
}
private static int dEncrypt(int el, final int r, final int s, final int e0, final int e1, final int[] sArr) {
int v = r ^ r >>> 16;
int u = v & e0;
v &= e1;
u = u ^ u << 16 ^ r ^ sArr[s];
int t = v ^ v << 16 ^ r ^ sArr[s + 1];
t = t >>> 4 | t << 28;
el ^= SP_TRANS[1][t & 0x3f] | SP_TRANS[3][t >>> 8 & 0x3f] | SP_TRANS[5][t >>> 16 & 0x3f] |
SP_TRANS[7][t >>> 24 & 0x3f] | SP_TRANS[0][u & 0x3f] | SP_TRANS[2][u >>> 8 & 0x3f] |
SP_TRANS[4][u >>> 16 & 0x3f] | SP_TRANS[6][u >>> 24 & 0x3f];
return el;
}
private static int[] desSetKey(final byte[] key) {
final int[] schedule = new int[32];
int c = fourBytesToInt(key, 0);
int d = fourBytesToInt(key, 4);
final int[] results = new int[2];
permOp(d, c, 4, 0xf0f0f0f, results);
d = results[0];
c = results[1];
c = hPermOp(c, -2, 0xcccc0000);
d = hPermOp(d, -2, 0xcccc0000);
permOp(d, c, 1, 0x55555555, results);
d = results[0];
c = results[1];
permOp(c, d, 8, 0xff00ff, results);
c = results[0];
d = results[1];
permOp(d, c, 1, 0x55555555, results);
d = results[0];
c = results[1];
d = (d & 0xff) << 16 | d & 0xff00 | (d & 0xff0000) >>> 16 | (c & 0xf0000000) >>> 4;
c &= 0xfffffff;
int j = 0;
for (int i = 0; i < 16; i++) {
if (SHIFT2[i]) {
c = c >>> 2 | c << 26;
d = d >>> 2 | d << 26;
} else {
c = c >>> 1 | c << 27;
d = d >>> 1 | d << 27;
}
c &= 0xfffffff;
d &= 0xfffffff;
int s = SKB[0][c & 0x3f] | SKB[1][c >>> 6 & 0x3 | c >>> 7 & 0x3c] |
SKB[2][c >>> 13 & 0xf | c >>> 14 & 0x30] |
SKB[3][c >>> 20 & 0x1 | c >>> 21 & 0x6 | c >>> 22 & 0x38];
final int t = SKB[4][d & 0x3f] | SKB[5][d >>> 7 & 0x3 | d >>> 8 & 0x3c] | SKB[6][d >>> 15 & 0x3f] |
SKB[7][d >>> 21 & 0xf | d >>> 22 & 0x30];
schedule[j++] = (t << 16 | s & 0xffff);
s = s >>> 16 | t & 0xffff0000;
s = s << 4 | s >>> 28;
schedule[j++] = s;
}
return schedule;
}
private static int fourBytesToInt(final byte[] b, int offset) {
final byte b4 = b[offset++];
int value = b4 & 0xff;
final byte b3 = b[offset++];
value |= (b3 & 0xff) << 8;
final byte b2 = b[offset++];
value |= (b2 & 0xff) << 16;
final byte b1 = b[offset ];
value |= (b1 & 0xff) << 24;
return value;
}
private static int hPermOp(int a, final int n, final int m) {
final int t = (a << 16 - n ^ a) & m;
a = a ^ t ^ t >>> 16 - n;
return a;
}
private static void intToFourBytes(final int iValue, final byte[] b, int offset) {
b[offset++] = (byte) (iValue & 0xff);
b[offset++] = (byte) (iValue >>> 8 & 0xff);
b[offset++] = (byte) (iValue >>> 16 & 0xff);
b[offset ] = (byte) (iValue >>> 24 & 0xff);
}
private static void permOp(int a, int b, final int n, final int m, final int[] results) {
final int t = (a >>> n ^ b) & m;
a ^= t << n;
b ^= t;
results[0] = a;
results[1] = b;
}
public int hashCode() {
return multiHashOrdered(Arrays.hashCode(hash), salt);
}
public boolean equals(final Object obj) {
if (! (obj instanceof UnixDESCryptPasswordImpl)) {
return false;
}
UnixDESCryptPasswordImpl other = (UnixDESCryptPasswordImpl) obj;
return salt == other.salt && Arrays.equals(hash, other.hash);
}
private void readObject(ObjectInputStream ignored) throws NotSerializableException {
throw new NotSerializableException();
}
Object writeReplace() {
return UnixDESCryptPassword.createRaw(getAlgorithm(), salt, hash);
}
public UnixDESCryptPasswordImpl clone() {
return this;
}
}