using System;
using System.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg
{
/// The string to key specifier class.
public class S2k
: BcpgObject
{
private const int ExpBias = 6;
public const int Simple = 0;
public const int Salted = 1;
public const int SaltedAndIterated = 3;
public const int GnuDummyS2K = 101;
public const int GnuProtectionModeNoPrivateKey = 1;
public const int GnuProtectionModeDivertToCard = 2;
internal int type;
internal HashAlgorithmTag algorithm;
internal byte[] iv;
internal int itCount = -1;
internal int protectionMode = -1;
internal S2k(
Stream inStr)
{
type = inStr.ReadByte();
algorithm = (HashAlgorithmTag) inStr.ReadByte();
//
// if this happens we have a dummy-S2k packet.
//
if (type != GnuDummyS2K)
{
if (type != 0)
{
iv = new byte[8];
if (Streams.ReadFully(inStr, iv, 0, iv.Length) < iv.Length)
throw new EndOfStreamException();
if (type == 3)
{
itCount = inStr.ReadByte();
}
}
}
else
{
inStr.ReadByte(); // G
inStr.ReadByte(); // N
inStr.ReadByte(); // U
protectionMode = inStr.ReadByte(); // protection mode
}
}
public S2k(
HashAlgorithmTag algorithm)
{
this.type = 0;
this.algorithm = algorithm;
}
public S2k(
HashAlgorithmTag algorithm,
byte[] iv)
{
this.type = 1;
this.algorithm = algorithm;
this.iv = iv;
}
public S2k(
HashAlgorithmTag algorithm,
byte[] iv,
int itCount)
{
this.type = 3;
this.algorithm = algorithm;
this.iv = iv;
this.itCount = itCount;
}
public virtual int Type
{
get { return type; }
}
/// The hash algorithm.
public virtual HashAlgorithmTag HashAlgorithm
{
get { return algorithm; }
}
/// The IV for the key generation algorithm.
public virtual byte[] GetIV()
{
return Arrays.Clone(iv);
}
[Obsolete("Use 'IterationCount' property instead")]
public long GetIterationCount()
{
return IterationCount;
}
/// The iteration count
public virtual long IterationCount
{
get { return (16 + (itCount & 15)) << ((itCount >> 4) + ExpBias); }
}
/// The protection mode - only if GnuDummyS2K
public virtual int ProtectionMode
{
get { return protectionMode; }
}
public override void Encode(
BcpgOutputStream bcpgOut)
{
bcpgOut.WriteByte((byte) type);
bcpgOut.WriteByte((byte) algorithm);
if (type != GnuDummyS2K)
{
if (type != 0)
{
bcpgOut.Write(iv);
}
if (type == 3)
{
bcpgOut.WriteByte((byte) itCount);
}
}
else
{
bcpgOut.WriteByte((byte) 'G');
bcpgOut.WriteByte((byte) 'N');
bcpgOut.WriteByte((byte) 'U');
bcpgOut.WriteByte((byte) protectionMode);
}
}
}
}