Applied Cryptography: Protocols, Algorithms, and Source Code in C

Category: Mathematics
Author: Bruce Schneier
All Stack Overflow 21
This Month Stack Overflow 5


by anonymous   2019-07-21
  1. It depends on the 2nd question. You must "pad" the message with something until it is a multiple of the block size. The pad bytes are added to the message before the MAC is calculated but only the original message is transmitted/stored/etc.

    For a MAC, the easiest thing to do is pad with zeros. However this has a vulnerability - if the message part ends in one or more zeros, an attacker could add or remove zeros and not change the MAC. But if you do step 2, this and another attack are both mitigated.

  2. If you prepend the length of the message before the message (e.g. not just in the first block, but the first thing in the first block), it mitigates the ability to sometimes add/remove zeros. It also mitigates an attackers ability to forge a message with an entire arbitrary extra block added. So this is a good thing to do. And it is a good idea for completely practical reasons too - you know how many bytes the message is without relying on any external means.

    It does not matter what the format of the length is - some encoded ASCII version or binary. However as a practical matter it should always be simple binary.

    There is no reason that the number of bits in the length must match the cipher block size. The size of the length field must be large enough to represent the message sizes. For example, if the message size could range from 0 to 1000 bytes long, you could prepend an unsigned 16 bit integer.

    This is done first before the MAC is calculated on both the sender and receiver. In essence the length is verified at the same time as the rest of the message, eliminating the ability for an attacker to forge a longer or shorter message.

There are many open source C implementations of block ciphers like AES that would be easy to find and get working.

Caveat Presumably the purpose of the question is just for learning. Any serious use should consider a stronger MAC such as suggested by other comments and a good crypto library. There are other weaknesses and attacks that can be very subtle so you should never attempt to implement your own crypto. Neither of us are crypto experts and this should be done only for learning.

BTW, I recommend both of the following books by Bruce Schneier:

by moonshadow   2019-07-21

Security is hard.

Don't roll your own login protocol, either use an existing proven one or do something trivial and robust over an encrypted (SSH, SSL...) connection. There are so many robust drop-in implementations of proven protocols out there, and so many examples of systems failing due to flawed reinvention of wheels - if the login is protecting anything of any importance at all, there is simply no excuse.

That said, if your purpose here is to learn to design such algorithms, I strongly recommend Bruce Schneier's "Applied Cryptography".

by anonymous   2019-07-21

There are two basic kinds of encryption algorithms in use today:

Private key cryptography, which uses the same key to encrypt and decrypt the message. This type is also known as symmetric key cryptography.

Public key cryptography, which uses a public key to encrypt the message and a private key to decrypt it. The name public key comes from the fact that you can make the encryption key public without compromising the secrecy of the message or the decryption key. Public key systems are also known as asymmetric key cryptography. . This book is nice one regarding this


U can read this patent is talking about US Patent 6769062 - Method and system of using an insecure crypto-accelerator

Read this

by anonymous   2019-07-21

You can do this with the Bouncy Castle Crypto APIs,

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
KeyPair key = keyGen.generateKeyPair();
PrivateKey priv = key.getPrivate();
PublicKey pub = key.getPublic();
String privateKey = new String(Base64.encode(priv.getEncoded(), 0,priv.getEncoded().length, Base64.NO_WRAP));
String publicKey1 = new String(Base64.encode(pub.getEncoded(), 0,pub.getEncoded().length, Base64.NO_WRAP));
String publicKey = new String(Base64.encode(publicKey1.getBytes(),0, publicKey1.getBytes().length, Base64.NO_WRAP));

As far as adding things like name, email and password, you are referring to generating a certificate, which requires that a key pair is generated. Certificate types vary depending on usage, as does the means to generate them.

If you wish to truly secure communications, is an important read, since poorly generated certificate and key exchanges are worse than no cryptography at all.

by sideshowmel   2019-02-01
by anonymous   2017-08-20

A general rule of thumb involving encryption is, if you haven't done it before, you're going to do it wrong. If the encryption is important, then use someone else's package (that you have source to, preferably, so that they don't introduce backdoors), because they will have ironed out the bugs. Check out Schneier's book on Crypto for some general equations and implementations.

But, if you just want to use encryption and not really mess with implementing it (even if that's just copying over code from the book), then check out the encryption namespace that others have mentioned.

by anonymous   2017-08-20

You generally would not encrypt a string using the public key of an X.509 directly. Instead you would generate a strong random(of a specific quality) key; use normal symmetric encryption (such as AES) and then encyrpt the string with that. You then encrypt the random key with the X.509.

Consult a good PKI/Crypto book (e.g. as to why (sections on key leakage, bit-flipping, padding and (re)encrypting twice).

If you really insist on doing this -have a look at its pkcs7_encode_rinfo function.

x509cert = ... something to read your x509 byte array in.

unsigned char *stuff = "Some zecret string";
int stufflen = strlen(stuff);

EVP_PKEY *pkey;

assert(pkey =  = X509_get_pubkey( x509cert));
assert(pctx = EVP_PKEY_CTX_new(pkey, NULL));
assert((EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT
                      EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri)==1);

size_t eklen;
assert(EVP_PKEY_encrypt(pctx, NULL, &eklen, stuff, stufflen)==1);

ek = OPENSSL_malloc(eklen);

unsigned char *ek = NULL;
assert((EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen)==1);

printf("Encrypted blurp: ");
for(int i = 0; i < eklen; i++) {
    printf("0x%02X ", ek[i];
by anonymous   2017-08-20

The bottom line is, you can't. See any other comment here for the reasons why. Even encryption software like PGP/GPG stores the keys in a file, and then stridently urges those files to be kept on a flash drive in a safe, or something else secure. Keys stored as part of executable code will be discovered.

In fact, if you're trying to encrypt anything on a client machine that will be decrypted by the client as part of normal operations, that is also a fool's errand. The client machines are inherently insecure, and you can't control what they're going to be able to do to your data.

If you're trying to authenticate, instead, look at Internet based authentication with logins to a server, or some kind of generated KeyCode that is used to validate the software.

Secret keys as part of a Public-Private Keypair should be kept in data files that can be secured. Symmetric keys should be generated on the fly as Session Keys, then discarded. Always assume that anyone who has a Secret or Session key on their computer will be able to discover it, and use it against your intentions.

Read "Applied Cryptography" by Bruce Schneier for more information.