User Tools

Site Tools


linux:kernel-hash-sha256
#include <unistd.h>
#include <string.h> // memcpy
#include <sys/socket.h>
#include <sys/sendfile.h>
#include <linux/if_alg.h>
#include <linux/socket.h>
 
#include <array>
#include <memory>
 
using sha256_t = std::array<unsigned char, 32>;
 
sha256_t sha256sum(int in, size_t buffer_size = 2048)
{
	std::unique_ptr<char> buffer(new char[buffer_size]);
 
	sha256_t digest;
 
	struct sockaddr_alg sa;
	sa.salg_family = AF_ALG;
	memcpy(sa.salg_type, "hash", 5);
	memcpy(sa.salg_name, "sha256", 7);
 
	int i, sockfd, fd;
 
	sockfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
	if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
		perror("bind");
		exit(EXIT_FAILURE);
	}
 
	fd = accept(sockfd, NULL, 0);
	if (fd < 0) {
		perror("accept");
		exit(EXIT_FAILURE);
	}
 
	// "pipe" the in fd to the hash algorithm
	int pos;
	int bytes_read;
	while ((bytes_read = read(in, buffer.get(), buffer_size)) > 0)
	{
		pos = 0;
		while (pos < bytes_read)
		{
			int sent = send(fd, buffer.get()+pos, bytes_read-pos, MSG_MORE);
			if (sent < 0)
			{
				perror("send");
				exit(EXIT_FAILURE);
			}
			pos += wrote;
		}
	}
	send(fd, nullptr, 0, 0); // "flush" the hash
 
	pos = 0;
	while (pos < sizeof(sha256_t))
	{
		int bytes = read(fd, digest.data()+pos, sizeof(sha256_t)-pos);
		if (bytes < 0) {
			perror("read");
			exit(EXIT_FAILURE);		
		}
		pos += bytes;
	}
	close(fd);
	close(sockfd);
 
	return digest;
}
 
int main(void)
{
	sha256_t digest = sha256sum(STDIN_FILENO);
 
	for (size_t i = 0; i < sizeof(sha256_t); i++) {
		printf("%02x",digest[i]);
	}
	printf("\n");
	return 0;
}

Und hier der Vergleich:

georg@machariel ~/tmp $ echo Hello World! | sha256sum 
03ba204e50d126e4674c005e04d82e84c21366780af1f43bd54a37816b6ab340  -
georg@machariel ~/tmp $ echo Hello World! | ./test-cpp 
03ba204e50d126e4674c005e04d82e84c21366780af1f43bd54a37816b6ab340

Edit: Hmm .. bei Dateien größer dem Puffer kommt ein anderer Hash raus … EDIT2: send mit MSG_MORE und der “flush” hat es gebracht :)

georg@machariel ~/tmp $ cat /boot/vmlinuz-4.0.5-slim | sha256sum
737c973c99fd9317f3e3decfbbec9c674a29643894ace462c0786d8e634f8183  -
georg@machariel ~/tmp $ cat /boot/vmlinuz-4.0.5-slim | ./test-cpp 
737c973c99fd9317f3e3decfbbec9c674a29643894ace462c0786d8e634f8183

Da ich bei dieser Version nicht genau weis ob es sich

a) bei dem fd um eine Pipe,
b) ein File 
c) oder sonstiges handelt 

kann ich kein seek verwenden um die Länge der Datei herauszufinden und damit kann ich auch kein sendfile nutzen. Also bleibt nur der Weg über den Userspace.

This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information
linux/kernel-hash-sha256.txt · Last modified: 2016/06/07 16:45 (external edit)