Moohar Archive

Vectors and matrices

16th March 2025

I’m almost ready to implement AES encryption. In truth, I've already done this, I've just not documented how. I was tempted to not to document it as part of this blog and instead write a more formal guide to TLS as a whole once I'd implemented everything and got HTTPS working. I still might take that approach going forward but I felt I should at least complete this series of posts on AES, just in case anyone was following along.

And I promise, in my next post I will finally get to the actual AES algorithm. First however, there is one last piece of mathematics I need to remind myself about, that is multiplying vectors with matrices.

A vector is something that contains multiple numbers as opposed to a scalar which is a single number. In geometry for example a vector is used to define a line which requires both a direction and a length. In computers we would typically use an array or tuple to store a vector. In modern programming a vector often refers to a specific type of data structure that implements a variable sized array. The computer version could certainly be used to store the mathematical version of a vector, but is not the only option, a normal fixed sized array is perfectly fine, preferable really. For the rest of this post, when I refer to a vector I mean the mathematical definition and not the data structure.

It seems to be convention to write vectors as a column of numbers in brackets, especially when doing maths with them.

[ 1 2 ]

A matrix is a 2D array of numbers. If you think of a vector as a column of numbers, a matrix is a rectangle.

[ 34 56 ] 2 by 2 matrix [ 34 56 78 ] 2 by 3 matrix [ 34 ] 2 by 1 matrix [ 0123 4567 89ab cdef ] 4 by 4 matrix

To multiply a matrix by a vector, you take each number in a row from the matrix, and multiply those numbers by each number from the vector and add the results to get a number for a new vector. The simplest example of this is multiplying a one row matrix by a vector.

[ 34 ] [ 1 2 ] = [(3×1)+(4×2)] = [11]

For matrices with multiple rows. You repeat the process for each row in the matrix to generate a new value in the resulting vector.

[ 34 56 ] [ 1 2 ] = [ (3×1)+(4×2) (5×1)+(6×2) ] = [ 11 17 ]

In general if the width of the matrix matches the height (size) of the vector, they can be multiplied and will result in a new vector with a height equal to the matrix.

[ 34 56 78 ] [ 1 2 ] = [ (3×1)+(4×2) (5×1)+(6×2) (7×1)+(8×2) ] = [ 11 17 23 ]

That said, most of the time, especially when doing calculations with them, you will use a square matrix because the input and output vectors will be the same size. This leads us to the identity matrices that will return the exact same vector as given. This is a square matrix with the elements on the diagonal from top left to bottom right set to 1 and the other elements set to 0. Working through an example shows why this works.

[ 100 010 001 ] [ 2 5 6 ] = [ (1×2)+ (0×5)+ (0×6) (0×2)+ (1×5)+ (0×6) (0×2)+ (0×5)+ (1×6) ] = [ 2 5 6 ]

Code

Unsurprisingly the code to perform this multiplication is basically nested loops.

void mxv(size_t width, size_t height, int matrix[height][width], int vector[width], int result[height]) {
	for (size_t h=0; h<height; h++) {
		result[h] = 0;
		for (size_t w=0; w<width; w++) {
			result[h] += matrix[h][w] * vector[w];
		}
	}
}

Some test code to show how it works:

void dump_vector(size_t size, int vector[size]) {
	for (size_t i=0; i<size; i++) {
		printf("%d\n", vector[i]);
	}
}

void test() {
	enum {width = 2, height = 3};

	int matrix[height][width] = {
		{3, 4},
		{5, 6},
		{7, 8}
	};
	int vector[width] = {1, 2};

	int result[height];
	mxv(width, height, matrix, vector, result);
	dump_vector(height, result);
}

And the output:

11
17
23

Multiplying matrices

Not required for AES but for completeness you can also multiply two matrices together assuming the width of the first is equal to the height of the second. The progress is the same as with a vector but repeated for each column of the second vector with the result being a new square matrix.

[ ab cd ef ] [ ghi jkl ] = [ ag+bj ah+bk ai+bl cg+dj ch+dk ci+dl eg+fj eh+fk ei+fl ]

TC