From 8102600bf98b69c4a73d7b79faf6b6ca3035a8d6 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Fri, 30 Sep 2022 14:12:30 +0700 Subject: Refactoring --- .../pqc/crypto/crystals/kyber/KyberParameters.cs | 14 +++++------ crypto/src/pqc/crypto/falcon/FalconParameters.cs | 22 +++++------------- crypto/src/pqc/crypto/frodo/FrodoParameters.cs | 12 ++++------ .../pqc/crypto/ntruprime/NtruLPRimeParameters.cs | 26 ++++++++++----------- .../pqc/crypto/ntruprime/SNtruPrimeParameters.cs | 23 ++++++++++-------- crypto/src/pqc/crypto/picnic/PicnicParameters.cs | 14 +++++------ crypto/src/pqc/crypto/saber/SABERParameters.cs | 11 ++++----- .../src/pqc/crypto/sphincsplus/HarakaS256Digest.cs | 15 +++--------- .../src/pqc/crypto/sphincsplus/HarakaS512Digest.cs | 15 ++++-------- crypto/src/pqc/crypto/sphincsplus/HarakaSBase.cs | 2 +- crypto/src/pqc/crypto/sphincsplus/HarakaSXof.cs | 27 ++++++++++------------ .../pqc/crypto/sphincsplus/SPHINCSPlusEngine.cs | 2 -- .../crypto/sphincsplus/SPHINCSPlusParameters.cs | 19 ++++++++------- 13 files changed, 85 insertions(+), 117 deletions(-) (limited to 'crypto/src/pqc') diff --git a/crypto/src/pqc/crypto/crystals/kyber/KyberParameters.cs b/crypto/src/pqc/crypto/crystals/kyber/KyberParameters.cs index f1a4ae921..00bc3950b 100644 --- a/crypto/src/pqc/crypto/crystals/kyber/KyberParameters.cs +++ b/crypto/src/pqc/crypto/crystals/kyber/KyberParameters.cs @@ -1,12 +1,10 @@ -using System; using Org.BouncyCastle.Crypto; namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber { - public class KyberParameters + public sealed class KyberParameters : ICipherParameters { - public static KyberParameters kyber512 = new KyberParameters("kyber512", 2, 128, false); public static KyberParameters kyber768 = new KyberParameters("kyber768", 3, 192, false); public static KyberParameters kyber1024 = new KyberParameters("kyber1024", 4, 256, false); @@ -14,23 +12,23 @@ namespace Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber public static KyberParameters kyber768_aes = new KyberParameters("kyber768-aes", 3, 192, true); public static KyberParameters kyber1024_aes = new KyberParameters("kyber1024-aes", 4, 256, true); - - private String m_name; + private string m_name; private int m_sessionKeySize; private KyberEngine m_engine; - public KyberParameters(String name, int k, int sessionKeySize, bool usingAes) + public KyberParameters(string name, int k, int sessionKeySize, bool usingAes) { m_name = name; this.m_sessionKeySize = sessionKeySize; m_engine = new KyberEngine(k, usingAes); } - public String Name => m_name; + public string Name => m_name; public int K => m_engine.K; + public int SessionKeySize => m_sessionKeySize; internal KyberEngine Engine => m_engine; } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/falcon/FalconParameters.cs b/crypto/src/pqc/crypto/falcon/FalconParameters.cs index c07591942..4a9bc598f 100644 --- a/crypto/src/pqc/crypto/falcon/FalconParameters.cs +++ b/crypto/src/pqc/crypto/falcon/FalconParameters.cs @@ -1,38 +1,28 @@ -using System; using Org.BouncyCastle.Crypto; namespace Org.BouncyCastle.Pqc.Crypto.Falcon { - public class FalconParameters + public sealed class FalconParameters : ICipherParameters { public static FalconParameters falcon_512 = new FalconParameters("falcon512", 9, 40); public static FalconParameters falcon_1024 = new FalconParameters("falcon1024", 10, 40); - private String name; + private string name; private uint logn; private uint nonce_length; - private FalconParameters(String name, uint logn, uint nonce_length) + private FalconParameters(string name, uint logn, uint nonce_length) { this.name = name; this.logn = logn; this.nonce_length = nonce_length; } - public uint LogN - { - get { return logn; } - } + public uint LogN => logn; - public uint NonceLength - { - get { return nonce_length; } - } + public uint NonceLength => nonce_length; - public string Name - { - get { return name; } - } + public string Name => name; } } diff --git a/crypto/src/pqc/crypto/frodo/FrodoParameters.cs b/crypto/src/pqc/crypto/frodo/FrodoParameters.cs index 1e28a22bf..69d3e5de6 100644 --- a/crypto/src/pqc/crypto/frodo/FrodoParameters.cs +++ b/crypto/src/pqc/crypto/frodo/FrodoParameters.cs @@ -1,14 +1,11 @@ - -using System; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; namespace Org.BouncyCastle.Pqc.Crypto.Frodo { - public class FrodoParameters + public sealed class FrodoParameters : ICipherParameters { - private static short[] cdf_table640 = {4643, 13363, 20579, 25843, 29227, 31145, 32103, 32525, 32689, 32745, 32762, 32766, 32767}; private static short[] cdf_table976 = {5638, 15915, 23689, 28571, 31116, 32217, 32613, 32731, 32760, 32766, 32767}; private static short[] cdf_table1344 = {9142, 23462, 30338, 32361, 32725, 32765, 32767}; @@ -22,7 +19,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Frodo public static FrodoParameters frodokem43088r3 = new FrodoParameters("frodokem43088", 1344, 16, 4, cdf_table1344, new ShakeDigest(256), new FrodoMatrixGenerator.Aes128MatrixGenerator(1344, (1<<16))); public static FrodoParameters frodokem43088shaker3 = new FrodoParameters("frodokem43088shake", 1344, 16, 4, cdf_table1344, new ShakeDigest(256), new FrodoMatrixGenerator.Shake128MatrixGenerator(1344, (1<<16))); - private String name; + private string name; private int n; private int d; private int b; @@ -32,7 +29,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.Frodo private int defaultKeySize; private FrodoEngine engine; - public FrodoParameters(String name, int n, int d, int b, short[] cdf_table, IDigest digest, FrodoMatrixGenerator mGen) + public FrodoParameters(string name, int n, int d, int b, short[] cdf_table, IDigest digest, + FrodoMatrixGenerator mGen) { this.name = name; this.n = n; @@ -49,7 +47,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Frodo public int N => n; - public String Name => name; + public string Name => name; public int D => d; diff --git a/crypto/src/pqc/crypto/ntruprime/NtruLPRimeParameters.cs b/crypto/src/pqc/crypto/ntruprime/NtruLPRimeParameters.cs index a8601250e..eac349267 100644 --- a/crypto/src/pqc/crypto/ntruprime/NtruLPRimeParameters.cs +++ b/crypto/src/pqc/crypto/ntruprime/NtruLPRimeParameters.cs @@ -1,19 +1,17 @@ using System; -using System.ComponentModel; + using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Digests; -using Org.BouncyCastle.Crypto.Modes; namespace Org.BouncyCastle.Pqc.Crypto.NtruPrime { - public class NtruLPRimeParameters : ICipherParameters + public sealed class NtruLPRimeParameters + : ICipherParameters { - - private String name; + private string name; private int p; private int q; private int _roundedBytes; - private bool LPR; + private bool m_LPR; private int _w; private int _rqBytes; private int _tau0; @@ -26,13 +24,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.NtruPrime private int _defaultKeySize; private NtruPrimeEngine _primeEngine; - private NtruLPRimeParameters(String name, int p, int q, bool LPR, int w, int tau0, + private NtruLPRimeParameters(string name, int p, int q, bool LPR, int w, int tau0, int tau1, int tau2, int tau3, int skBytes, int pkBytes, int ctBytes, int roundedBytes, int rqBytes, int defaultKeySize) { this.name = name; this.p = p; this.q = q; - this.LPR = LPR; + m_LPR = LPR; this._w = w; this._tau0 = tau0; this._tau1 = tau1; @@ -55,15 +53,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.NtruPrime public static NtruLPRimeParameters ntrulpr953 = new NtruLPRimeParameters("NTRU_LPRime_953", 953, 6343, true, 345, 2997,82,2798,400,1652,1349,1477, 1317, -1, 192); public static NtruLPRimeParameters ntrulpr1013 = new NtruLPRimeParameters("NTRU_LPRime_1013", 1013, 7177, true, 392, 3367,73,3143,449,1773,1455,1583, 1423, -1, 192); public static NtruLPRimeParameters ntrulpr1277 = new NtruLPRimeParameters("NTRU_LPRime_1277", 1277, 7879, true, 429, 3724,66,3469,496,2231,1847,1975, 1815, -1, 256); - + public int P => p; - public bool lpr => LPR; - + + public bool LPR => m_LPR; + public int Q => q; public int DefaultKeySize => _defaultKeySize; - - internal NtruPrimeEngine PrimeEngine => _primeEngine; + internal NtruPrimeEngine PrimeEngine => _primeEngine; } } diff --git a/crypto/src/pqc/crypto/ntruprime/SNtruPrimeParameters.cs b/crypto/src/pqc/crypto/ntruprime/SNtruPrimeParameters.cs index 95d63d1a8..4ec03a497 100644 --- a/crypto/src/pqc/crypto/ntruprime/SNtruPrimeParameters.cs +++ b/crypto/src/pqc/crypto/ntruprime/SNtruPrimeParameters.cs @@ -1,15 +1,17 @@ using System; + using Org.BouncyCastle.Crypto; namespace Org.BouncyCastle.Pqc.Crypto.NtruPrime { - public class SNtruPrimeParameters : ICipherParameters + public sealed class SNtruPrimeParameters + : ICipherParameters { - private String name; + private string name; private int p; private int q; private int _roundedBytes; - private bool LPR; + private bool m_LPR; private int _w; private int _rqBytes; private int _tau0; @@ -21,13 +23,13 @@ namespace Org.BouncyCastle.Pqc.Crypto.NtruPrime private int _ctBytes; private int _defaultKeySize; private NtruPrimeEngine _primeEngine; - private SNtruPrimeParameters(String name, int p, int q, bool LPR, int w, int tau0, - int tau1, int tau2, int tau3, int skBytes, int pkBytes, int ctBytes, int roundedBytes, int rqBytes, int defaultKeySize) + private SNtruPrimeParameters(string name, int p, int q, bool LPR, int w, int tau0, int tau1, int tau2, int tau3, + int skBytes, int pkBytes, int ctBytes, int roundedBytes, int rqBytes, int defaultKeySize) { this.name = name; this.p = p; this.q = q; - this.LPR = LPR; + m_LPR = LPR; this._w = w; this._tau0 = tau0; this._tau1 = tau1; @@ -50,14 +52,15 @@ namespace Org.BouncyCastle.Pqc.Crypto.NtruPrime public static SNtruPrimeParameters sntrup953 = new SNtruPrimeParameters("SNTRU_Prime_953", 953, 6343, false, 396, -1,-1,-1,-1,2254,1505,1349, 1317, 1505, 192); public static SNtruPrimeParameters sntrup1013 = new SNtruPrimeParameters("SNTRU_Prime_1013", 1013, 7177, false, 448, -1,-1,-1,-1,2417,1623,1455, 1423, 1623, 192); public static SNtruPrimeParameters sntrup1277 = new SNtruPrimeParameters("SNTRU_Prime_1277", 1277, 7879, false, 492, -1,-1,-1,-1,3059,2067,1847, 1815, 2067, 256); - + public int P => p; - public bool lpr => LPR; - + + public bool LPR => m_LPR; + public int Q => q; public int DefaultKeySize => _defaultKeySize; - internal NtruPrimeEngine PrimeEngine => _primeEngine; + internal NtruPrimeEngine PrimeEngine => _primeEngine; } } diff --git a/crypto/src/pqc/crypto/picnic/PicnicParameters.cs b/crypto/src/pqc/crypto/picnic/PicnicParameters.cs index ed2030054..24ade6676 100644 --- a/crypto/src/pqc/crypto/picnic/PicnicParameters.cs +++ b/crypto/src/pqc/crypto/picnic/PicnicParameters.cs @@ -4,9 +4,9 @@ using Org.BouncyCastle.Crypto; namespace Org.BouncyCastle.Pqc.Crypto.Picnic { - public class PicnicParameters + public sealed class PicnicParameters : ICipherParameters - { + { public static PicnicParameters picnicl1fs = new PicnicParameters("picnicl1fs", 1); public static PicnicParameters picnicl1ur = new PicnicParameters("picnicl1ur", 2); public static PicnicParameters picnicl3fs = new PicnicParameters("picnicl3fs", 3); @@ -20,18 +20,16 @@ namespace Org.BouncyCastle.Pqc.Crypto.Picnic public static PicnicParameters picnicl3full = new PicnicParameters("picnicl3full", 11); public static PicnicParameters picnicl5full = new PicnicParameters("picnicl5full", 12); - private String name; + private string name; private int param; - private PicnicParameters(String name, int param) + + private PicnicParameters(string name, int param) { this.name = name; this.param = param; } - public String GetName() - { - return name; - } + public string Name => name; internal PicnicEngine GetEngine() { diff --git a/crypto/src/pqc/crypto/saber/SABERParameters.cs b/crypto/src/pqc/crypto/saber/SABERParameters.cs index 50b577ab8..f558e29bd 100644 --- a/crypto/src/pqc/crypto/saber/SABERParameters.cs +++ b/crypto/src/pqc/crypto/saber/SABERParameters.cs @@ -4,10 +4,9 @@ using Org.BouncyCastle.Crypto; namespace Org.BouncyCastle.Pqc.Crypto.Saber { - public class SABERParameters + public sealed class SABERParameters : ICipherParameters { - public static SABERParameters lightsaberkem128r3 = new SABERParameters("lightsaberkem128r3", 2, 128); public static SABERParameters saberkem128r3 = new SABERParameters("saberkem128r3", 3, 128); public static SABERParameters firesaberkem128r3 = new SABERParameters("firesaberkem128r3", 4, 128); @@ -20,12 +19,12 @@ namespace Org.BouncyCastle.Pqc.Crypto.Saber public static SABERParameters saberkem256r3 = new SABERParameters("saberkem256r3", 3, 256); public static SABERParameters firesaberkem256r3 = new SABERParameters("firesaberkem256r3", 4, 256); - private String name; + private string name; private int l; private int defaultKeySize; private SABEREngine engine; - public SABERParameters(String name, int l, int defaultKeySize) + public SABERParameters(string name, int l, int defaultKeySize) { this.name = name; this.l = l; @@ -33,7 +32,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.Saber this.engine = new SABEREngine(l, defaultKeySize); } - public String Name => name; + public string Name => name; public int L => l; @@ -44,4 +43,4 @@ namespace Org.BouncyCastle.Pqc.Crypto.Saber return engine; } } -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/sphincsplus/HarakaS256Digest.cs b/crypto/src/pqc/crypto/sphincsplus/HarakaS256Digest.cs index 65f75b068..58086cede 100644 --- a/crypto/src/pqc/crypto/sphincsplus/HarakaS256Digest.cs +++ b/crypto/src/pqc/crypto/sphincsplus/HarakaS256Digest.cs @@ -2,7 +2,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus { - internal class HarakaS256Digest + internal sealed class HarakaS256Digest : HarakaSBase { public HarakaS256Digest(HarakaSXof harakaSXof) @@ -10,10 +10,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus haraka256_rc = harakaSXof.haraka256_rc; } - public String GetAlgorithmName() - { - return "HarakaS-256"; - } + public string AlgorithmName => "HarakaS-256"; public int GetDigestSize() { @@ -23,9 +20,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus public void BlockUpdate(byte input) { if (off + 1 > 32) - { throw new ArgumentException("total input cannot be more than 32 bytes"); - } buffer[off++] = input; } @@ -33,9 +28,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus public void BlockUpdate(byte[] input, int inOff, int len) { if (off + len > 32) - { throw new ArgumentException("total input cannot be more than 32 bytes"); - } Array.Copy(input, inOff, buffer, off, len); off += len; @@ -51,7 +44,5 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus return output.Length; } - } - -} \ No newline at end of file +} diff --git a/crypto/src/pqc/crypto/sphincsplus/HarakaS512Digest.cs b/crypto/src/pqc/crypto/sphincsplus/HarakaS512Digest.cs index a1c1e3db9..aa3adbc71 100644 --- a/crypto/src/pqc/crypto/sphincsplus/HarakaS512Digest.cs +++ b/crypto/src/pqc/crypto/sphincsplus/HarakaS512Digest.cs @@ -8,7 +8,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus * Haraka512-256 with reference to Python Reference Impl from: https://github.com/sphincs/sphincsplus *

*/ - internal class HarakaS512Digest + internal sealed class HarakaS512Digest : HarakaSBase { public HarakaS512Digest(HarakaSBase harakaSBase) @@ -16,31 +16,26 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus haraka512_rc = harakaSBase.haraka512_rc; } - public String GetAlgorithmName() - { - return "HarakaS-512"; - } + public string AlgorithmName => "HarakaS-512"; public int GetDigestSize() { return 64; } - public void BlockUpdate(byte input) + public void Update(byte input) { if (off + 1 > 64) - { throw new ArgumentException("total input cannot be more than 64 bytes"); - } + buffer[off++] = input; } public void BlockUpdate(byte[] input, int inOff, int len) { if (off + len > 64) - { throw new ArgumentException("total input cannot be more than 64 bytes"); - } + Array.Copy(input, inOff, buffer, off, len); off += len; } diff --git a/crypto/src/pqc/crypto/sphincsplus/HarakaSBase.cs b/crypto/src/pqc/crypto/sphincsplus/HarakaSBase.cs index 8af826dba..bad948a22 100644 --- a/crypto/src/pqc/crypto/sphincsplus/HarakaSBase.cs +++ b/crypto/src/pqc/crypto/sphincsplus/HarakaSBase.cs @@ -10,7 +10,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus * Haraka512-256 with reference to Python Reference Impl from: https://github.com/sphincs/sphincsplus *

*/ - internal class HarakaSBase + internal abstract class HarakaSBase { internal ulong[][] haraka512_rc = new ulong[][]{ new ulong[]{0x24cf0ab9086f628bL, 0xbdd6eeecc83b8382L, 0xd96fb0306cdad0a7L, 0xaace082ac8f95f89L, 0x449d8e8870d7041fL, 0x49bb2f80b2b3e2f8L, 0x0569ae98d93bb258L, 0x23dc9691e7d6a4b1L}, diff --git a/crypto/src/pqc/crypto/sphincsplus/HarakaSXof.cs b/crypto/src/pqc/crypto/sphincsplus/HarakaSXof.cs index 97bd3c07c..210ac35e1 100644 --- a/crypto/src/pqc/crypto/sphincsplus/HarakaSXof.cs +++ b/crypto/src/pqc/crypto/sphincsplus/HarakaSXof.cs @@ -2,13 +2,10 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus { - internal class HarakaSXof + internal sealed class HarakaSXof : HarakaSBase { - public String GetAlgorithmName() - { - return "Haraka-S"; - } + public string AlgorithmName => "Haraka-S"; public HarakaSXof(byte[] pkSeed) { @@ -26,6 +23,16 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus } } + public void Update(byte input) + { + buffer[off++] ^= input; + if (off == 32) + { + Haraka512Perm(buffer); + off = 0; + } + } + public void BlockUpdate(byte[] input, int inOff, int len) { int i = inOff, j, loop = (len + off) >> 5; @@ -44,16 +51,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus } } - public void BlockUpdate(byte input) - { - buffer[off++] ^= input; - if (off == 32) - { - Haraka512Perm(buffer); - off = 0; - } - } - public int DoFinal(byte[] output, int outOff, int len) { int outLen = len; diff --git a/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusEngine.cs b/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusEngine.cs index 85c50f3c4..778367a57 100644 --- a/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusEngine.cs +++ b/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusEngine.cs @@ -347,7 +347,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus return mask; } - } internal class Shake256Engine @@ -359,7 +358,6 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus public Shake256Engine(bool robust, int n, uint w, uint d, int a, int k, uint h) : base(robust, n, w, d, a, k, h) { - this.treeDigest = new ShakeDigest(256); this.maskDigest = new ShakeDigest(256); } diff --git a/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusParameters.cs b/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusParameters.cs index 2a5f6d581..9714ed847 100644 --- a/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusParameters.cs +++ b/crypto/src/pqc/crypto/sphincsplus/SPHINCSPlusParameters.cs @@ -244,16 +244,16 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus paramsToOid[SPHINCSPlusParameters.haraka_256s] = sphincsPlus_haraka_256s_robust; } - private String name; + private string name; private ISPHINCSPlusEngineProvider engineProvider; - private SPHINCSPlusParameters(String name, ISPHINCSPlusEngineProvider engineProvider) + private SPHINCSPlusParameters(string name, ISPHINCSPlusEngineProvider engineProvider) { this.name = name; this.engineProvider = engineProvider; } - public String Name => name; + public string Name => name; internal int N => engineProvider.N; @@ -270,7 +270,7 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus */ public static SPHINCSPlusParameters GetParams(uint id) { - return (SPHINCSPlusParameters)oidToParams[id]; + return oidToParams[id]; } /** @@ -290,7 +290,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus } } - class Sha2EngineProvider : ISPHINCSPlusEngineProvider + internal class Sha2EngineProvider + : ISPHINCSPlusEngineProvider { private readonly bool robust; private readonly int n; @@ -319,7 +320,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus } } - class Shake256EngineProvider : ISPHINCSPlusEngineProvider + internal class Shake256EngineProvider + : ISPHINCSPlusEngineProvider { private readonly bool robust; private readonly int n; @@ -348,7 +350,8 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus } } - class Haraka256EngineProvider : ISPHINCSPlusEngineProvider + internal class Haraka256EngineProvider + : ISPHINCSPlusEngineProvider { private readonly bool robust; private readonly int n; @@ -376,4 +379,4 @@ namespace Org.BouncyCastle.Pqc.Crypto.SphincsPlus return new SPHINCSPlusEngine.HarakaSEngine(robust, n, w, d, a, k, h); } } -} \ No newline at end of file +} -- cgit 1.4.1