80 lines · 1.8 KB · Java
RawDownload
package plan9.auth; import java.util.Arrays; import java.security.*;import java.security.interfaces.*;import java.security.spec.*; import java.security.SecureRandom;import java.security.spec.AlgorithmParameterSpec;import java.security.NoSuchAlgorithmException;import java.security.GeneralSecurityException;import java.security.Key; import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;import javax.crypto.NoSuchPaddingException; public class RandomAES implements Random { 	private static final int AESbsize = 128/8;	// block size in bytes 	private byte[]	counter = new byte[AESbsize];	private Cipher	cipher;	private byte[]	data;	private int offset; 	private static class AESKey implements Key {		byte[]	key; 		AESKey(byte[] a){			key = Arrays.copyOf(a, a.length);		}		public byte[] getEncoded(){			return Arrays.copyOf(key, key.length);		}		public String getAlgorithm(){			return "AES";		}		public String getFormat(){			return "RAW";		}	}; 	private static final void inc(byte[] a){		for(int i = 0; i < a.length; i++)			if(++a[i] == 0)				break;	} 	public RandomAES() throws GeneralSecurityException {		byte[] seed = new byte[AESbsize];		Aids.memrandom(seed, 0, seed.length);		cipher = Cipher.getInstance("AES/ECB/NoPadding");		cipher.init(Cipher.ENCRYPT_MODE, new AESKey(seed));		offset = AESbsize;	} 	public synchronized void randombytes(byte[] a, int o, int n){		for(int i = 0; i < n;){			int avail = AESbsize - offset;			if(data == null || avail == 0){				inc(counter);				try{					data = cipher.doFinal(counter);				}catch(GeneralSecurityException e){					throw new RuntimeException("impossible failure in memrandom", e);				}				offset = 0;				avail = AESbsize;			}			int l = n - i;			if(l > avail)				l = avail;			System.arraycopy(data, offset, a, o+i, avail);			offset += avail;			n -= avail;		}	}}