Reputation: 191
{
KeyGenerator keyGen = KeyGenerator.getInstance("DES");
SecretKey myKey = keyGen.generateKey();
byte[] data = myKey.getEncoded();
String encodedKey;
encodedKey = Base64.getEncoder().encodeToString(data);
System.out.println("My key1 :" +myKey);
System.out.println("My key2 :" +encodedKey);
System.out.println("My key3 :" +data);
}
it returns
My key1 :com.sun.crypto.provider.DESKey@fffe79f6
My key2 :dg61j8hRCNY=
My key3 :[B@2ac1fdc4
Could u guys tell me how do i get 7 bytes KEY , no more KEY PREFIX com.sun.crypto.provider.DESKey
Because i want to save my 7 chars ASCII into a file to HIDE it somewhere in the planet.
Upvotes: 2
Views: 413
Reputation: 298103
You have different issues here.
If you don’t want to store the parity bit, you can drop it as follows:
static byte[] dropParity(byte[] desKey) {
if(desKey.length!=8) throw new IllegalArgumentException();
BitSet in=BitSet.valueOf(desKey);
BitSet out=new BitSet(56);
for(int byteIndex=0, inIndex=0, outIndex=0; byteIndex<8; byteIndex++, inIndex++)
for(int bitIndex=0; bitIndex<7; bitIndex++) out.set(outIndex++, in.get(inIndex++));
byte[] byteArray = out.toByteArray();
if(byteArray.length<7) // last byte(s) are zero
byteArray=Arrays.copyOf(byteArray, 7);
return byteArray;
}
static byte[] regenerateParity(byte[] desKey) {
if(desKey.length!=7) throw new IllegalArgumentException();
BitSet in=BitSet.valueOf(desKey);
BitSet out=new BitSet(64);
for(int byteIndex=0, inIndex=0, outIndex=0; byteIndex<8; byteIndex++)
{
boolean even=true;
for(int bitIndex=0; bitIndex<7; bitIndex++) {
final boolean bit = in.get(inIndex++);
out.set(outIndex++, bit);
even ^= bit;
}
out.set(outIndex++, even);
}
return out.toByteArray();
}
These two methods allow to convert the eight byte array to a seven byte array and back by dropping and regenerating the parity bit. Keep in mind that these bytes are not ASCII characters.
If you want to transfer a key through a channel which only accepts ASCII characters, you may use a direct encoding which uses seven bits per character. As said, that will still occupy eight bytes per key.
static String dropParityAndConvertToASCII(byte[] desKey) {
if(desKey.length!=8) throw new IllegalArgumentException();
char[] ch=new char[8];
for(int i=0; i<8; i++) ch[i]=(char)((desKey[i]>>1)&0x7F);
return new String(ch);
}
static byte[] convertFromASCIIAndAddParityBit(String desKey) {
if(desKey.length()!=8) throw new IllegalArgumentException();
byte[] ba=new byte[8];
for(int i = 0; i < 8; i++) {
int b = desKey.charAt(i)<<1;
ba[i] = (byte)(b | Integer.bitCount(b)&1^1);
}
return ba;
}
The obstacle here is that the parity bit is the lowest bit while the unused bit of the ASCII encoding is the highest. So the key bytes are shifted by one bit and the highest bit set to zero to create ASCII bytes. When converting back, the value are shifted back and the parity bit is recalculated.
But note that not all ASCII characters are printable characters. If you want an encoding that is displayable, you have to resort to an encoding like Base64 and live with the fact that it produces more characters than key bytes.
Upvotes: 1
Reputation: 8211
The byte array data
is the key you are asking for.
However, it is NOT in ASCII.
If you want to save it as text (ASCII), that's why you have to use an encoded format, e.g. using base64, like your encodedKey
.
You can read it back later, and base64 decode it and get back the 7 byte key data
.
Upvotes: 1