<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.2" />

HssPrivateKeyParameters

using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.IO; using System; using System.Collections.Generic; using System.IO; using System.Runtime.CompilerServices; namespace Org.BouncyCastle.Pqc.Crypto.Lms { public class HssPrivateKeyParameters : LmsKeyParameters, ILmsContextBasedSigner { private readonly int m_level; private readonly bool m_isShard; private IList<LmsPrivateKeyParameters> m_keys; private IList<LmsSignature> m_sig; private readonly long m_indexLimit; private long m_index; private HssPublicKeyParameters m_publicKey; [Obsolete("Use 'Level' instead")] public int L { get { return m_level; } } public int Level => m_level; public long IndexLimit => m_indexLimit; public HssPrivateKeyParameters(int l, IList<LmsPrivateKeyParameters> keys, IList<LmsSignature> sig, long index, long indexLimit) : base(true) { m_level = l; m_isShard = false; m_keys = new List<LmsPrivateKeyParameters>(keys); m_sig = new List<LmsSignature>(sig); m_index = index; m_indexLimit = indexLimit; ResetKeyToIndex(); } private HssPrivateKeyParameters(int l, IList<LmsPrivateKeyParameters> keys, IList<LmsSignature> sig, long index, long indexLimit, bool isShard) : base(true) { m_level = l; m_isShard = isShard; m_keys = new List<LmsPrivateKeyParameters>(keys); m_sig = new List<LmsSignature>(sig); m_index = index; m_indexLimit = indexLimit; } public static HssPrivateKeyParameters GetInstance(byte[] privEnc, byte[] pubEnc) { return Parse(privEnc, 0, privEnc.Length, HssPublicKeyParameters.Parse(pubEnc)); } public static HssPrivateKeyParameters GetInstance(object src) { HssPrivateKeyParameters hssPrivateKeyParameters = src as HssPrivateKeyParameters; if (hssPrivateKeyParameters != null) return hssPrivateKeyParameters; BinaryReader binaryReader = src as BinaryReader; if (binaryReader != null) return Parse(binaryReader); Stream stream = src as Stream; if (stream != null) return Parse(stream); byte[] array = src as byte[]; if (array != null) return Parse(array); DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(13, 1); defaultInterpolatedStringHandler.AppendLiteral("cannot parse "); defaultInterpolatedStringHandler.AppendFormatted<object>(src); throw new ArgumentException(defaultInterpolatedStringHandler.ToStringAndClear()); } internal static HssPrivateKeyParameters Parse(BinaryReader binaryReader) { if (BinaryReaders.ReadInt32BigEndian(binaryReader) != 0) throw new Exception("unknown version for HSS private key"); int num = BinaryReaders.ReadInt32BigEndian(binaryReader); long index = BinaryReaders.ReadInt64BigEndian(binaryReader); long indexLimit = BinaryReaders.ReadInt64BigEndian(binaryReader); bool isShard = binaryReader.ReadBoolean(); List<LmsPrivateKeyParameters> list = new List<LmsPrivateKeyParameters>(num); for (int i = 0; i < num; i++) { list.Add(LmsPrivateKeyParameters.Parse(binaryReader)); } List<LmsSignature> list2 = new List<LmsSignature>(num - 1); for (int j = 1; j < num; j++) { list2.Add(LmsSignature.Parse(binaryReader)); } return new HssPrivateKeyParameters(num, list, list2, index, indexLimit, isShard); } internal static HssPrivateKeyParameters Parse(Stream stream) { return BinaryReaders.Parse(Parse, stream, true); } internal static HssPrivateKeyParameters Parse(byte[] buf) { return BinaryReaders.Parse(Parse, new MemoryStream(buf, false), false); } internal static HssPrivateKeyParameters Parse(byte[] buf, int off, int len) { return BinaryReaders.Parse(Parse, new MemoryStream(buf, off, len, false), false); } internal static HssPrivateKeyParameters Parse(byte[] buf, int off, int len, HssPublicKeyParameters publicKey) { HssPrivateKeyParameters hssPrivateKeyParameters = Parse(buf, off, len); hssPrivateKeyParameters.m_publicKey = publicKey; return hssPrivateKeyParameters; } public long GetIndex() { lock (this) { return m_index; } } public LmsParameters[] GetLmsParameters() { lock (this) { int count = m_keys.Count; LmsParameters[] array = new LmsParameters[count]; for (int i = 0; i < count; i++) { LmsPrivateKeyParameters lmsPrivateKeyParameters = m_keys[i]; array[i] = new LmsParameters(lmsPrivateKeyParameters.SigParameters, lmsPrivateKeyParameters.OtsParameters); } return array; } } internal void IncIndex() { lock (this) { m_index++; } } private static HssPrivateKeyParameters MakeCopy(HssPrivateKeyParameters privateKeyParameters) { return Parse(privateKeyParameters.GetEncoded()); } protected void UpdateHierarchy(IList<LmsPrivateKeyParameters> newKeys, IList<LmsSignature> newSig) { lock (this) { m_keys = new List<LmsPrivateKeyParameters>(newKeys); m_sig = new List<LmsSignature>(newSig); } } public bool IsShard() { return m_isShard; } public long GetUsagesRemaining() { return IndexLimit - GetIndex(); } internal LmsPrivateKeyParameters GetRootKey() { return m_keys[0]; } public HssPrivateKeyParameters ExtractKeyShard(int usageCount) { lock (this) { if (usageCount < 0) throw new ArgumentOutOfRangeException("cannot be negative", "usageCount"); if (usageCount > m_indexLimit - m_index) throw new ArgumentException("exceeds usages remaining in current leaf", "usageCount"); long index = m_index; long indexLimit = m_index += usageCount; List<LmsPrivateKeyParameters> keys = new List<LmsPrivateKeyParameters>(GetKeys()); List<LmsSignature> sig = new List<LmsSignature>(GetSig()); HssPrivateKeyParameters result = MakeCopy(new HssPrivateKeyParameters(m_level, keys, sig, index, indexLimit, true)); ResetKeyToIndex(); return result; } } public IList<LmsPrivateKeyParameters> GetKeys() { lock (this) { return m_keys; } } internal IList<LmsSignature> GetSig() { lock (this) { return m_sig; } } private void ResetKeyToIndex() { IList<LmsPrivateKeyParameters> keys = GetKeys(); long[] array = new long[keys.Count]; long num = GetIndex(); for (int num2 = keys.Count - 1; num2 >= 0; num2--) { LMSigParameters sigParameters = keys[num2].SigParameters; int num3 = (1 << sigParameters.H) - 1; array[num2] = (num & num3); num >>= sigParameters.H; } bool flag = false; LmsPrivateKeyParameters rootKey = GetRootKey(); if (m_keys[0].GetIndex() - 1 != array[0]) { m_keys[0] = Lms.GenerateKeys(rootKey.SigParameters, rootKey.OtsParameters, (int)array[0], rootKey.GetI(), rootKey.GetMasterSecret()); flag = true; } for (int i = 1; i < array.Length; i++) { LmsPrivateKeyParameters lmsPrivateKeyParameters = m_keys[i - 1]; int n = lmsPrivateKeyParameters.OtsParameters.N; byte[] array2 = new byte[16]; byte[] array3 = new byte[n]; SeedDerive seedDerive = new SeedDerive(lmsPrivateKeyParameters.GetI(), lmsPrivateKeyParameters.GetMasterSecret(), LmsUtilities.GetDigest(lmsPrivateKeyParameters.OtsParameters)); seedDerive.Q = (int)array[i - 1]; seedDerive.J = -2; seedDerive.DeriveSeed(true, array3, 0); byte[] array4 = new byte[n]; seedDerive.DeriveSeed(false, array4, 0); Array.Copy(array4, 0, array2, 0, array2.Length); bool flag2 = (i < array.Length - 1) ? (array[i] == m_keys[i].GetIndex() - 1) : (array[i] == m_keys[i].GetIndex()); if (!Arrays.AreEqual(array2, m_keys[i].GetI()) || !Arrays.AreEqual(array3, m_keys[i].GetMasterSecret())) { m_keys[i] = Lms.GenerateKeys(keys[i].SigParameters, keys[i].OtsParameters, (int)array[i], array2, array3); m_sig[i - 1] = Lms.GenerateSign(m_keys[i - 1], m_keys[i].GetPublicKey().ToByteArray()); flag = true; } else if (!flag2) { m_keys[i] = Lms.GenerateKeys(keys[i].SigParameters, keys[i].OtsParameters, (int)array[i], array2, array3); flag = true; } } if (flag) UpdateHierarchy(m_keys, m_sig); } public HssPublicKeyParameters GetPublicKey() { lock (this) { return new HssPublicKeyParameters(m_level, GetRootKey().GetPublicKey()); } } internal void ReplaceConsumedKey(int d) { LMOtsPrivateKey currentOtsKey = m_keys[d - 1].GetCurrentOtsKey(); int n = currentOtsKey.Parameters.N; SeedDerive derivationFunction = currentOtsKey.GetDerivationFunction(); derivationFunction.J = -2; byte[] array = new byte[n]; derivationFunction.DeriveSeed(true, array, 0); byte[] array2 = new byte[n]; derivationFunction.DeriveSeed(false, array2, 0); byte[] array3 = new byte[16]; Array.Copy(array2, 0, array3, 0, array3.Length); List<LmsPrivateKeyParameters> list = new List<LmsPrivateKeyParameters>(m_keys); LmsPrivateKeyParameters lmsPrivateKeyParameters = m_keys[d]; list[d] = Lms.GenerateKeys(lmsPrivateKeyParameters.SigParameters, lmsPrivateKeyParameters.OtsParameters, 0, array3, array); List<LmsSignature> list2 = new List<LmsSignature>(m_sig); list2[d - 1] = Lms.GenerateSign(list[d - 1], list[d].GetPublicKey().ToByteArray()); m_keys = new List<LmsPrivateKeyParameters>(list); m_sig = new List<LmsSignature>(list2); } public override bool Equals(object obj) { if (this == obj) return true; HssPrivateKeyParameters hssPrivateKeyParameters = obj as HssPrivateKeyParameters; if (hssPrivateKeyParameters != null && m_level == hssPrivateKeyParameters.m_level && m_isShard == hssPrivateKeyParameters.m_isShard && m_indexLimit == hssPrivateKeyParameters.m_indexLimit && m_index == hssPrivateKeyParameters.m_index && CompareLists(m_keys, hssPrivateKeyParameters.m_keys)) return CompareLists(m_sig, hssPrivateKeyParameters.m_sig); return false; } public override byte[] GetEncoded() { lock (this) { Composer composer = Composer.Compose().U32Str(0).U32Str(m_level) .U64Str(m_index) .U64Str(m_indexLimit) .Boolean(m_isShard); foreach (LmsPrivateKeyParameters key in m_keys) { composer.Bytes(key); } foreach (LmsSignature item in m_sig) { composer.Bytes(item); } return composer.Build(); } } public override int GetHashCode() { int level = m_level; level = 31 * level + m_isShard.GetHashCode(); level = 31 * level + m_keys.GetHashCode(); level = 31 * level + m_sig.GetHashCode(); level = 31 * level + m_indexLimit.GetHashCode(); return 31 * level + m_index.GetHashCode(); } protected object Clone() { return MakeCopy(this); } public LmsContext GenerateLmsContext() { int level = Level; LmsPrivateKeyParameters lmsPrivateKeyParameters = default(LmsPrivateKeyParameters); LmsSignedPubKey[] array = default(LmsSignedPubKey[]); lock (this) { Hss.RangeTestKeys(this); IList<LmsPrivateKeyParameters> keys = GetKeys(); IList<LmsSignature> sig = GetSig(); lmsPrivateKeyParameters = GetKeys()[level - 1]; int i = 0; array = new LmsSignedPubKey[level - 1]; for (; i < level - 1; i++) { array[i] = new LmsSignedPubKey(sig[i], keys[i + 1].GetPublicKey()); } IncIndex(); } return lmsPrivateKeyParameters.GenerateLmsContext().WithSignedPublicKeys(array); } public byte[] GenerateSignature(LmsContext context) { try { return Hss.GenerateSignature(Level, context).GetEncoded(); } catch (IOException ex) { throw new Exception("unable to encode signature: " + ex.Message, ex); } } private static bool CompareLists<T>(IList<T> arr1, IList<T> arr2) { for (int i = 0; i < ((ICollection<T>)arr1).Count && i < ((ICollection<T>)arr2).Count; i++) { if (!object.Equals(arr1[i], arr2[i])) return false; } return true; } } }