/// <summary> /// Number of samples must be greater than 8 * Number_of_secret_bytes + 32 for LSB without indexes. /// If this system have specified indexes, then number of samples cannot be less than maximum value from indexes array. /// </summary> /// <param name="af"></param> /// <param name="secret"></param> /// <returns></returns> protected override bool CheckContainerCapacity(AudioFile af, byte[] secret) { if (Indexes == null) return (af.Header.NumSamples / 8 - 32)>= secret.Length; else { int max = af.Header.NumSamples; var test = Indexes.Where(x => x > max); return test.Count() == 0; } }
protected abstract bool CheckContainerCapacity(AudioFile af, byte[] secret);
protected byte[] Extract(AudioFile af) { Header hdr = af.Header; int sampleSize = hdr.BlockAlign; int start = af.DataStartIndex + sampleSize - 1; if (Indexes == null) { int stop = af.Data.Length; int dataIndex = start; //odkoduj długość danych do ukrycia byte[] lArr = new byte[4]; for (byte i = 0; i < 4; ++i) { for (byte idx = 0; idx < 8; ++idx) { //przypisz byte lsb = (byte)(af.Data[dataIndex] % 2); lArr[i] += (byte)(lsb << idx); //przesun dataIndex += sampleSize; } } int secretLenght = BitConverter.ToInt32(lArr, 0); byte[] secret = new byte[secretLenght]; for (int i = 0; i < secretLenght; ++i) { for (byte idx = 0; idx < 8; ++idx) { //przypisz byte lsb = (byte)(af.Data[dataIndex] % 2); secret[i] += (byte)(lsb << idx); //przesun dataIndex += sampleSize; } } return secret; } else { int nr = 0; int secretLength = Indexes.Length / 8; byte[] secret = new byte[secretLength]; int dataIndex; for (int i = 0; i < secretLength; ++i) { for (byte idx = 0; idx < 8; ++idx) { //ustaw index dataIndex = start + sampleSize * Indexes[nr++]; //przypisz byte lsb = (byte)(af.Data[dataIndex] % 2); secret[i] += (byte)(lsb << idx); } } return secret; } }
protected void Hide(AudioFile af, byte[] secret) { if (Indexes == null) { Header hdr = af.Header; int step = hdr.BlockAlign; int start = af.DataStartIndex + step - 1; int stop = af.Data.Length; int dataIndex = start; //zakoduj długość danych do ukrycia int secretLength = secret.Length; var lArr = BitConverter.GetBytes(secretLength); foreach (byte lghByte in lArr) { for (byte bitIndex = 0; bitIndex < 8; ++bitIndex) { //przypisz if (((lghByte >> bitIndex) & 1) == 0) { if (af.Data[dataIndex] % 2 == 1) af.Data[dataIndex] -= 1; } else { if (af.Data[dataIndex] % 2 == 0) af.Data[dataIndex] += 1; } //przesun dataIndex += step; } } //w każdej kolejnej próbce umieszczamy po kolejnym bicie sekretu, począwszy od najmłodszego foreach (byte srtByte in secret) { for (byte bitIndex = 0; bitIndex < 8; ++bitIndex) { //przypisz if ((srtByte >> bitIndex) % 2 == 0) { if (af.Data[dataIndex] % 2 == 1) af.Data[dataIndex] -= 1; } else { if (af.Data[dataIndex] % 2 == 0) af.Data[dataIndex] += 1; } //przesun dataIndex += step; } } } else { Header hdr = af.Header; int sampleSize = hdr.BlockAlign; int start = af.DataStartIndex + sampleSize - 1; int nr = 0; int dataIndex; foreach (byte srtByte in secret) { for (byte bitIndex = 0; bitIndex < 8; ++bitIndex) { //ustaw index dataIndex = start + sampleSize * Indexes[nr++]; //przypisz if ((srtByte >> bitIndex) % 2 == 0) { if (af.Data[dataIndex] % 2 == 1) af.Data[dataIndex] -= 1; } else { if (af.Data[dataIndex] % 2 == 0) af.Data[dataIndex] += 1; } } } } }