This is a bit of a cross-posted question which I first asked at StackOverflow, however I was not satisfied with stackoverflow, so I came here for an in depth answer.

I, as they say, "rolled my own cryptosystem". It is a C# CTR encryption method, that is modified. Based off of this diagram:

CTR mode

I hate the idea of padding, so instead of padding, it just encrypts the remainder of the plaintext with a separate key called rpass. Please do not bash me for doing so. As I said, this is a homemade algorithm.

The plaintext is shortened to a length that makes it devide evenly, the remainder of the plaintext is the OTP-ed with rpass.

The passwords that are put into the function are at least 512 characters long.

The comments are there not for others to read, it is there for me to read. So if they don't make sense that's ok; I'm weird.

    public byte[] CTR(byte[] p, string key, string rkey)
        byte[] str = new byte[(p.Length-rkey.Length)]; // nicely evenly encrypted plaintext minus the remainder (currently ciphertext)

        byte[] str_ = new byte[rkey.Length]; // encrypted remainder part of the plaintext (currently ciphertext)

        byte[] p_r = new byte[rkey.Length]; // the plaintext remainder (currently plaintext)
        //p.CopyTo(p_r, p.Length - rkey.Length); // copies the last remainder of the plaintext to p_r so we can encrypt p_r and make it str_
        p_r = Copy(p, (p.Length - rkey.Length));
        byte[] full = new byte[p.Length];
        uint ii = 0;

        for (uint c = 0; c < ((p.Length - rkey.Length) / key.Length); c++)
            char[] kc = key.ToCharArray();
            char[] E = new char[key.Length];

            //char[] cc = c.ToString().ToCharArray();
            int inc = 0;
            foreach (char ch in kc)
                E[inc] = (char)(ch ^ c);

            byte[] Eb = Encoding.ASCII.GetBytes(E);

            for (int i = 0; i < E.Length; i++)
                str[ii] = (byte)(p[ii] ^ Eb[i]);
        } // str is now complete

        //encrypting p_r with rkey and placing it into str_, after that, we'll move it to full (Done with OTP)

        for (int i = 0; i < rkey.Length; i++)
            str_[i] = (byte)(p_r[i] ^ rkey[i]);

        // now that str_ now contains encrypted remainder (p_r), we're gonna make full

        str.CopyTo(full, 0);
        str_.CopyTo(full, str.Length);

        return full;

Copy() is another method, here:

    private byte[] Copy(byte[] original, int startingIO)
        byte[] mod = new byte[original.Length - startingIO];

        for (int i = 0; i < (original.Length - startingIO); i++)
            mod[i] = original[startingIO + i];
        return mod;

So if you can't understand what I'm asking, I am asking:

  • Is this algorithm secure enough to be implemented?
    (If you find flaws, please list them in detail.)

You ask: "Why not use AES, it has been reviewed by many people with years of experience"
Answer: I am doing this because I want to get "years of experience"

Of course, "This is not relevant", "How does this help the community?", "Off-topic" comments are going to come. But please help me out here. See - Codereview.SE users are not cryptographers, StackOverflow users didn't help very much either, and Security.SE users said my question was a cross-post and simply took it down. All in all, Crypto.SE seems to be the most logic place to ask this question.

  • $\begingroup$ This is at most one-time secure, since otherwise rpass will be reused. ​ ​ $\endgroup$
    – user991
    Mar 27 '16 at 1:28
  • $\begingroup$ BTW it's cryptographer! $\endgroup$
    – Alan Wolfe
    Mar 27 '16 at 1:28
  • 2
    $\begingroup$ CTR mode doesn't need padding to begin with. $\endgroup$
    – user13741
    Mar 27 '16 at 1:49
  • 2
    $\begingroup$ See How to publish a cipher for some pointers on what to do when developing your own ciphers, it has some good pointers. $\endgroup$
    – malexmave
    Mar 29 '16 at 14:05

This stream-cipher algorithm can be summarized like this:

$C_i = P_i \oplus K_j \oplus \frac{i}{|K|}$ with $j = i \, (mod \, |K|)$

Essentially, the key is repeated up to the length of the plaintext. The number of key repetitions is also added to the key, then the key-stream is added to the plaintext to produce the ciphertext byte. When $|K|$ does not divide $|P|$, then a second key is used to encrypt trailing bytes of plaintext.

One problem that I feel confident in pointing out, is that this is vulnerable to a chosen-plaintext attack. If the attacker is allowed to choose $P$ and sets:

$P_i = \frac{i}{n}$

he can learn that the key is just the first $n$ bytes of $C$ by guessing $n$ and checking that

$C_i = C_j$ with $j = i \, (mod \, n)$

which is satisfied when he guesses correctly.

Under this attack model, assuming a key-length of up to 512 bytes, the algorithm provides 9 bits of security.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.