首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Bouncy城堡实现TwoFish

用Bouncy城堡实现TwoFish
EN

Code Review用户
提问于 2017-06-14 15:40:43
回答 3查看 1.8K关注 0票数 5

经过大量的研究,我能够使用.NET的实现这两种算法。据我所知,这段代码已经过测试,并且正在完美地工作。但我不知道它是否得到了很好的执行,我想听听别人的意见。如果知道它是否正确,那就太好了,因为它将供其他开发人员使用。在安全性和性能方面有什么改进吗?有什么想法吗?

代码语言:javascript
复制
public class BCEngine
{
    private readonly Encoding _encoding;
    private readonly IBlockCipher _blockCipher;
    private PaddedBufferedBlockCipher _cipher;
    private IBlockCipherPadding _padding;

    public BCEngine()
    {

    }

    BCEngine(IBlockCipher blockCipher, Encoding encoding)
    {
        _blockCipher = blockCipher;
        _encoding = encoding;
    }

    #region Public Methods


    public static string TwoFishEncryption(string TextPlain, string Password, byte[] Salt)
    {
        Sha3Digest Sha3Digest = new Sha3Digest();
        Pkcs5S2ParametersGenerator gen = new Pkcs5S2ParametersGenerator(Sha3Digest);
        gen.Init(Encoding.UTF8.GetBytes(Password), Salt, 1000);
        KeyParameter param = (KeyParameter)gen.GenerateDerivedParameters(new TwofishEngine().AlgorithmName, 256);

        BCEngine bcEngine = new BCEngine(new TwofishEngine(), Encoding.UTF8);
        bcEngine.SetPadding(new Pkcs7Padding());
        return bcEngine.Encrypt(TextPlain, param);
    }

    public static string TwoFishDecryption(string TextEncripted, string Password, byte[] Salt)
    {
        Sha3Digest Sha3Digest = new Sha3Digest();
        Pkcs5S2ParametersGenerator gen = new Pkcs5S2ParametersGenerator(Sha3Digest);
        gen.Init(Encoding.UTF8.GetBytes(Password), Salt, 1000);
        KeyParameter param = (KeyParameter)gen.GenerateDerivedParameters(new TwofishEngine().AlgorithmName, 256);

        BCEngine bcEngine = new BCEngine(new TwofishEngine(), Encoding.UTF8);
        bcEngine.SetPadding(new Pkcs7Padding());
        return bcEngine.Decrypt(TextEncripted, param);
    }

    #endregion

    #region Private Methods

    void SetPadding(IBlockCipherPadding padding)
    {
        if (padding != null)
            _padding = padding;
    }

    string Encrypt(string plain, ICipherParameters SetKeyParameter)
    {
        byte[] result = BouncyCastleCrypto(true, _encoding.GetBytes(plain), SetKeyParameter);
        return Convert.ToBase64String(result);
    }

    string Decrypt(string cipher, ICipherParameters SetKeyParameter)
    {
        byte[] result = BouncyCastleCrypto(false, Convert.FromBase64String(cipher), SetKeyParameter);
        return _encoding.GetString(result, 0, result.Length);
    }

    byte[] BouncyCastleCrypto(bool forEncrypt, byte[] input, ICipherParameters SetKeyParameter)
    {
        try
        {
            _cipher = _padding == null ?
            new PaddedBufferedBlockCipher(_blockCipher) : new PaddedBufferedBlockCipher(_blockCipher, _padding);

            _cipher.Init(forEncrypt, SetKeyParameter);

            byte[] ret = _cipher.DoFinal(input);
            return ret;

        }
        catch (CryptoException ex)
        {
            // throw new CryptoException(ex);
        }
        return null;
    }

    #endregion

}
EN

回答 3

Code Review用户

回答已采纳

发布于 2017-06-14 16:20:48

静态与实例

公共BCEngine() {} BCEngine(IBlockCipher blockCipher,编码){ _blockCipher = blockCipher;_encoding =编码;}

默认构造函数应该为另一个构造函数初始化的两个字段提供合理的默认值,但是等待.这两个构造函数都是无用的,因为所有公共API都是静态的。唯一的实例成员是私有方法。我可以创建一个BCEngine实例,但是我不能用它做任何事情。

BCEngine bcEngine =新BCEngine(新的TwofishEngine(),Encoding.UTF8);bcEngine.SetPadding(新的Pkcs7Padding());返回的bcEngine.Encrypt(TextPlain,param);

但是再等等..。实例化它以调用私有实例方法。这是非常不一致和混乱的。

您应该使所有事物都是静态的,或者是所有的东西都是实例。

如果一个实例使用私有静态方法作为帮助器,这是可以的,但反过来则有点奇怪。至少默认构造函数也应该是私有的。

但是,您的实现使用私有字段,其中两个字段不是只读的,所以您可以使用它们来存储某种状态,但幸运的是它们不是静态的。您应该删除这些字段,并将所需的参数从一个方法传递到另一个方法。然后您将不需要任何实例,方法将是纯正 <-- LINK

使用和处置

您应该检查您的代码的一次性类型。我很肯定他们有很多。加密通常需要处理一些东西。

#区域

区域很少是必要的,对于成员分组来说,几乎从来没有必要。没有它们就更容易读懂代码。

票数 3
EN

Code Review用户

发布于 2017-06-14 16:55:45

  • 如果您的方法禁止某些值,您应该通知用户: void SetPadding(IBlockCipherPadding填充){ if (void != null) _padding =void;}如果值为null,则抛出一个异常。没有明确的迹象表明_padding没有设置为null。
  • TwoFishEncryption & TwoFishDecryption似乎具有几乎相同的主体,考虑重构重复的代码,只需在末尾调用1行代码即可。
  • 你的三值运算符排序有点不寻常。这在我看来更清晰:_cipher = _padding == null?新PaddedBufferedBlockCipher(_blockCipher):新PaddedBufferedBlockCipher(_blockCipher,_padding);
票数 3
EN

Code Review用户

发布于 2017-06-14 20:03:07

我已经根据反馈修改了代码,我希望它有所改进。我接受更多的建议!感谢所有帮助我的人!

代码语言:javascript
复制
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;
using Org.Cerberus.Utils;
using System;
using System.Text;

namespace BCEngine
{
    public class BCEngineCore
    {
        Encoding _encoding;
        IBlockCipher _blockCipher;
        private PaddedBufferedBlockCipher _cipher;
        private IBlockCipherPadding _padding;
        KeyParameter KeyParameter;

        #region Public Methods

        public string TwoFishEncryption(string TextPlain, string Password, byte[] Salt, string Prefix = "")
        {
            TwoFish(TextPlain, Password, Salt, Prefix);
            return Encrypt(TextPlain, KeyParameter);
        }

        public string TwoFishDecryption(string TextEncripted, string Password, byte[] Salt, string Prefix = "")
        {
            TwoFish(TextEncripted, Password, Salt, Prefix);
            return Decrypt(TextEncripted, KeyParameter);
        }

        #endregion

        #region Private Methods

        void TwoFish(string TextPlain, string Password, byte[] Salt, string Prefix = "")
        {

            Sha3Digest Sha3Digest = new Sha3Digest((int)KeySizes.F256);
            Pkcs5S2ParametersGenerator gen = new Pkcs5S2ParametersGenerator(Sha3Digest);
            gen.Init(Encoding.UTF8.GetBytes(Password), Salt.PreFixSaltBytes(Prefix), Constants.NUM_ITERATOR);
            KeyParameter = (KeyParameter)gen.GenerateDerivedParameters(BCEngines.TwofishEngine.AlgorithmName, 256);

            SetPadding(new Pkcs7Padding());
            SetBlockCipher(BCEngines.TwofishEngine);
            SetEncoding(Encoding.UTF8);
        }

        void SetPadding(IBlockCipherPadding padding)
        {
            if (padding != null)
                _padding = padding;
            else
                throw new NullReferenceException("Padding is null!");
        }

        void SetBlockCipher(IBlockCipher blockCipher)
        {
            if (blockCipher != null)
                _blockCipher = blockCipher;
            else
                throw new NullReferenceException("BlockCipher is null!");
        }

        void SetEncoding(Encoding encoding)
        {
            if (encoding != null)
                _encoding = encoding;
            else
                throw new NullReferenceException("Encoding is null!");
        }

        string Encrypt(string plain, ICipherParameters SetKeyParameter)
        {
            byte[] result = BouncyCastleCrypto(true, _encoding.GetBytes(plain), SetKeyParameter);
            return Convert.ToBase64String(result);
        }

        string Decrypt(string cipher, ICipherParameters SetKeyParameter)
        {
            byte[] result = BouncyCastleCrypto(false, Convert.FromBase64String(cipher), SetKeyParameter);
            return _encoding.GetString(result, 0, result.Length);
        }

        byte[] BouncyCastleCrypto(bool forEncrypt, byte[] input, ICipherParameters SetKeyParameter)
        {
            try
            {
                _cipher = _padding == null
                    ? new PaddedBufferedBlockCipher(_blockCipher)
                    : new PaddedBufferedBlockCipher(_blockCipher, _padding);

                _cipher.Init(forEncrypt, SetKeyParameter);

                byte[] ret = _cipher.DoFinal(input);
                return ret;

            }
            catch (CryptoException ex)
            {
                // throw new CryptoException(ex);
            }
            return null;
        }

        #endregion

    }

    public sealed class BCEngine
    {
        private static BCEngineCore instance;

        private BCEngine() { }

        public static BCEngineCore Instance
        {
            get
            {
                if (instance == null)
                    instance = new BCEngineCore();

                return instance;
            }
        }
    }

}
票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/165776

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档