Elsaの技術日記(徒然なるままに)

主に自分で作ったアプリとかの報告・日記を記載

MENU

PythonでC、C++で作成した動的ライブラリを読み込み

先日、Linux環境にてC++で動的ライブラリ作成方法についてまとめました。
ライブラリ化したコードをC++でリンクすれば使用したいコードがすぐに使えるのですが、
使用していてふと、、、
pythonなど他の言語で動的ライブラリを読むことは出来ないのだろうか??🤔
と思い、調べてみました。

今回はPythonで動的ライブラリを読み込んでみたいと思います。



■前提条件

今回使用する関数ですが、単純な足し算を行う、
int add(int,int)関数
と単純な引き算を行う、
int sub(int,int)関数
をライブラリ化して、pythonで読み出して結果を出力してみたいと思います。
また、ライブラリ化した際のライブラリ名を、
libhoge.so
とします。

C言語で作成した動的ライブラリをPythonで読み込んでみる

まずはC言語で作成した動的ライブラリをPythonで読み込んでみます。

動的ライブラリを読み込むにあたり、
ctypes
というライブラリを用います。
pythonのコードはこちらになります。

import ctypes

PATH_TO_LIB = "./libhoge.so"

libc = ctypes.CDLL(PATH_TO_LIB)
ret = libc.add(1,2)
print(ret)

ret = libc.sub(3,1)
print(ret)

C言語で作成したコードはこちら。
ファイル名:hoge.c

#include <stdio.h>

int add(int a, int b){
	return a+b;
}

int sub(int a,int b){
	return a-b;
}

こちらのhoge.cをコンパイルし、動的ライブラリを作成していきます。
コンパイル手順はこちら。

gcc -shared -fPIC -o libhoge.so hoge.c

実施すると、libhoge.soが生成されるのでさきほど作成したpythonコードと同階層に格納し、

python pythonコード名.py

のように実行すると、

3
2

と出力されるかと思います。

■C++言語で作成した動的ライブラリをPythonで読み込んでみる

次にC++言語で作成した動的ライブラリをPythonで読み込んでみます。
試しに先ほどのコードをcppファイルにして

g++ -shared -fPIC -o libhoge.so hoge.cpp

を実行してみましたが、、、

AttributeError: ./libhoge.so: undefined symbol: add

と出力されてしまい、ライブラリを正確に読み取れていないようです。

調べてみたところ、ctypesはC言語のみ対応しておりC++だと認識しないようです。
このため、
__cplusplusを用いて、C言語として読み込ませる必要があるとのこと。

そこで、
ファイル名:hoge.h

#include <stdio.h>

#ifdef __cplusplus
extern "C"{
#endif
    int add(int a, int b);
    int sub(int a,int b);
#ifdef __cplusplus
}
#endif

を作成し、cppファイルを

#include "hoge.h"

int add(int a, int b){
	return a+b;
}

int sub(int a,int b){
	return a-b;
}

と変更し再度、

g++ -shared -fPIC -o libhoge.so hoge.cpp

を実行しlibhoge.soを生成後、
先ほどのpythonコードを実行したところ、

3
2

を得ることが出来ました。

■最後に

今回はPythonでC、C++で作成した動的ライブラリを読み込んでみました。
今度は別の言語でライブラリ読み込めるのか確認していきたいと思います。



nodejsでパスワード付き圧縮ファイルを生成し、サーバーから送信してみる

前回、http requestを受けてからzip圧縮ファイルを生成しフロントエンドに圧縮したzipファイルを送信するまでを実施しました。
elsammit-beginnerblg.hatenablog.com

今回はzip圧縮だけではなくパスワードを付けて送信してみたいと思います。



■環境

前回と同様の構成で行きます。
f:id:Elsammit:20211108231936p:plain

言語はnodejs(サーバーサイドjavascritpt)です。

■パスワード付き圧縮ファイル生成コード その1

では早速パスワード付き圧縮ファイルを生成するコードを書いていきます。

まずはライブラリを用いてパスワード付きzipファイルを生成する方法からです。
今回用いるライブラリは、
「archiver-zip-encryptable」
です。
github.com

まず下記でライブラリをダウンロードしてきます。

npm i archiver-zip-encryptable

そして、archiver-zip-encryptableを用いたzipパスワード付き圧縮ファイルを生成するコードはこちらになります。

const fs = require('fs')
const archiver = require('archiver');

archiver.registerFormat('zip-encryptable', require('archiver-zip-encryptable'));

function zipCompression(){
    let zip_file_name = "src.zip";

    // ストリームを生成して、archiverと紐付ける
    var archive = archiver('zip-encryptable', {
        zlib: { level: 9 },
        encryptionMethod: 'aes256',
        password: 'test'
    });
    var output = fs.createWriteStream(zip_file_name);
    archive.pipe(output);

    archive.glob('img/*');
    
    // zip圧縮実行
    archive.finalize();
}

まず、

archiver.registerFormat('zip-encryptable', require('archiver-zip-encryptable'));

にてarchiverにパスワード付きzipを生成するように設定(定義)を行います。

後は'archiver生成時に、

    var archive = archiver('zip-encryptable', {
        zlib: { level: 9 },
        encryptionMethod: 'aes256',
        password: 'test'
    });

のように暗号化方式やパスワードをセットすればOK。
後は、zip圧縮と同様に、
にて圧縮ファイルに各データを入れていきます。
圧縮するデータはimgディレクトリ配下全てとしています。

こちらを実行するとsrc.zipが生成されており、解凍しようとするとパスワードを求められるかと思います。
さらに、パスワードに"test"と入力すると解凍が実行され、imgディレクトリ配下が格納されていることが確認できるかと思います。

■パスワード付き圧縮ファイル生成コード その2

先ほどはライブラリを用いてパスワード付きzip圧縮化を実施しました。

今度はサーバー側OSがLinux系に限定されてしまいますが、
新規にライブラリをダウンロードせずに実現する方法についてまとめていきます。

方法は、Linuxのコマンドをnodejs上で実行してしまう方法です。
コードはこちら。

const child = require('child_process');

function zipCompression(){
    var zip_file_name = "src.zip";

    spawn = child.spawn;
    zip = spawn('zip',['-P', 'password' , zip_file_name, "-r" , "img"]);
}

child_processを用いて、

spawn = child.spawn;
zip = spawn('zip',['-P', 'test' , zip_file_name, "-r" , "img"]);

で圧縮コマンドを実行していきます。

child_processについての詳細は下記を参考にしてください。
Child process | Node.js v17.1.0 Documentation

今回実施していることは、
zipコマンドで、-Pオプションを用いてパスワードを付与してzip圧縮するコードを生成させ、
実行しているのみです。

こちらも実行すると圧縮されたファイルが生成され、解凍する際にパスワード(test)の入力が求められるかと思います。

■requestに応じてパスワード付き圧縮ファイル生成しresponseするコード

最後は前回と同様に、パスワード付き圧縮ファイルを生成しresponseしてみたいと思います。
掲載するのはzip-encryptableライブラリを用いる方法です。

const fs = require('fs')
var http = require('http');
const archiver = require('archiver');

archiver.registerFormat('zip-encryptable', require('archiver-zip-encryptable'));

function zipFiles() {
    return new Promise(function (resolve){
        // 出力先のzipファイル名
        var zip_file_name = "src.zip";

        // ストリームを生成して、archiverと紐付ける
        var archive = archiver('zip-encryptable', {
            zlib: { level: 9 },
            encryptionMethod: 'aes256',
            password: 'test'
        });
        var output = fs.createWriteStream(zip_file_name);
        archive.pipe(output);

        archive.glob('img/*');
        
        // zip圧縮実行
        archive.finalize();
        output.on("close", function () {
            // zip圧縮完了すると発火する
            var archive_size = archive.pointer();
            console.log(`complete! total size : ${archive_size} bytes`);

            resolve(0);
        });
    });
}

function zipCompression(){
    var zip_file_name = "src.zip";

    // ストリームを生成して、archiverと紐付ける
    var archive = archiver('zip-encryptable', {
        zlib: { level: 9 },
        encryptionMethod: 'aes256',
        password: 'test'
    });
    var output = fs.createWriteStream(zip_file_name);
    archive.pipe(output);

    archive.glob('img/*');
    
    // zip圧縮実行
    archive.finalize();
}

http.createServer(function(req,res){
    zipFiles().then(function(data){
        var fileName = "src.zip";
        var contentDip = 'attachment; filename=' + fileName;
        
        res.writeHead(200, {
            'Content-Type': 'application/zip',
            'Content-Disposition' : contentDip
        });
        var readStream = fs.createReadStream('src.zip');

        readStream.pipe(res);
    });
}).listen(8080);

こちらのコードを実行後、

curl -o test.zip http://ipアドレス:8080/

というようにcurlコマンドでファイルをダウンロードすると、サーバーからデータがzip圧縮された状態で格納され、
解凍する際にはパスワードの入力が求められるかと思います。

■最後に

今回はパスワード付きzipファイルを生成する方法と、
http requestに応じて生成したパスワード付きzipファイルをresponseするまでをまとめてみました。



nodejsでzip圧縮してみる

先日、nodejsでzipやtar圧縮ファイルをサーバーからフロントへダウンロードしてみました。
elsammit-beginnerblg.hatenablog.com

今回はサーバーサイドにてzipファイルを圧縮してみます。
自分で圧縮したzipファイルをダウンロードするまでのコードを作成してみます。



■環境

今回も前回と同様にラズパイをサーバーと見立て、PCから指示を出すようにします。
言語も前回と同様、nodejsです。
f:id:Elsammit:20211108231936p:plain

■サーバーサイドでzipファイルを圧縮する。

ではzip圧縮するコードを記載します。
コードは下記になります。

const fs = require('fs')
var http = require('http');
const archiver = require('archiver');

function zipFiles(){
    // 出力先のzipファイル名
    var zip_file_name = "src.zip";

    // ストリームを生成して、archiverと紐付ける
    var archive = archiver.create('zip', {});

    var output = fs.createWriteStream(zip_file_name);
    archive.pipe(output);

    archive.glob('img/*');
    
    // zip圧縮実行
    archive.finalize();
    output.on("close", function () {
        // zip圧縮完了すると発火する
        var archive_size = archive.pointer();
        console.log(`complete! total size : ${archive_size} bytes`);
    });
}

http.createServer(function(req,res){
    zipFiles();
    res.writeHead(200, {'Content-Type': 'text/plain'}); 
    res.write('Hello World\n');
    res.end();
}).listen(8080);

圧縮のコードはこちらになります。

function zipFiles(){
    // 出力先のzipファイル名
    var zip_file_name = "src.zip";

    // ストリームを生成して、archiverと紐付ける
    var archive = archiver.create('zip', {});

    var output = fs.createWriteStream(zip_file_name);
    archive.pipe(output);

    archive.glob('img/*');
    
    // zip圧縮実行
    archive.finalize();
}

圧縮を行うにあたりarchiverライブラリを用います。

var archive = archiver.create('zip', {});

でzip圧縮する旨を示し、

    var output = fs.createWriteStream(zip_file_name);
    archive.pipe(output);

    archive.glob('img/*');

にて圧縮ファイルに各データを入れておきます。
圧縮するデータはimgディレクトリ配下全てとしています。

こちらのコードを実行し、http requestするとHello Worldとresponseが返ってくるのと、
少し時間が経過するとsrc.zipという名の圧縮ファイルが格納されます。
本圧縮ファイルを解凍するとimg配下のデータが格納されているかと思います。

■zipファイル圧縮したデータをダウンロードしてみる

では先日作成したzipファイルをダウンロードするコードと組み合わせ、
zipファイル位圧縮したデータをダウンロードするコードを記載します。
コードはこちら。

const fs = require('fs')
var http = require('http');
const archiver = require('archiver');

function zipFiles() {
    return new Promise(function (resolve){
        // 出力先のzipファイル名
        var zip_file_name = "src.zip";

        // ストリームを生成して、archiverと紐付ける
        var archive = archiver.create('zip', {});

        var output = fs.createWriteStream(zip_file_name);
        archive.pipe(output);

        archive.glob('img/*');
        
        // zip圧縮実行
        archive.finalize();
        output.on("close", function () {
            resolve(0);
        });
    });
}

http.createServer(function(req,res){
    zipFiles().then(function(data){
        var fileName = "src.zip";
        var contentDip = 'attachment; filename=' + fileName;
        
        res.writeHead(200, {
            'Content-Type': 'application/zip',
            'Content-Disposition' : contentDip
        });
        var readStream = fs.createReadStream('src.zip');

        readStream.pipe(res);
    });
}).listen(8080);

下記割り込み関数や、

        output.on("close", function () {
            resolve(0);
        });

非同期関数(Promise)を用いていますが、
他は同じコードになります。

このコードを実行した後、

curl -o test.zip http://ipアドレス:8080/

というようにcurlコマンドでファイルをダウンロードすると、サーバーからデータがzip圧縮された状態で格納されるかと思います。

■最後に

今回はサーバーサイドにてzipファイルを圧縮するコードについてまとめてみました。
ファイルの取り扱いについてもう少し学んでいきたいので、もう少し調査進めてみます。



zipやtar.gzなどの圧縮ファイルをサーバからhttpで送信する方法

今回は圧縮ファイルをhttpでサーバからフロントエンドに送信するための方法に関してまとめます。

ふと、フロントエンドからファイルを指定してアップロードは行えるけど、
圧縮ファイルをサーバーからフロントエンドに送信する方法ってどうやるんだろう??
と思い、調べてみました!!



■環境

今回、下図のようにラズパイをサーバーと見立て、
PCからzipファイルやtar.gzファイルをダウンロードしてみました。
f:id:Elsammit:20211108231936p:plain

使用した言語はnode jsです。

■zipファイル送信用サーバーサイドの実装

まず、zipファイルをhttp responseで返すためのサーバーサイドの実装をしていきます。
コードはこちら。

const fs = require('fs')
const http = require('http');

http.createServer(function(req,res){
    letfileName = "src.zip";
    let contentDip = 'attachment; filename=' + fileName;
    
    res.writeHead(200, {
        'Content-Type': 'application/zip',
        'Content-Disposition' : contentDip
    });
    var readStream = fs.createReadStream(fileName);
    readStream.pipe(res);
}).listen(8080);
});

ヘッダに対して、
Content-Typeにapplication/zipを指定することでzipを送信することを明示します。
Content-Dispositionはレスポンスヘッダーとして、コンテンツがブラウザーでインラインで表示されることを求められているか、
つまり、ウェブページとして表示するか、ウェブページの一部として表示するか、ダウンロードしてローカルに保存する添付ファイルとするかを示します。
詳細は下記に記載されておりますので詳しくはこちらをご参照ください。
developer.mozilla.org

後は、createReadStreamでファイルを読み込みながらレスポンスにpipeで流していきます。

こちらのコードを、

node ファイル名.js

などでサーバーを起動させ、

curl -o output.zip http://IPアドレス:8080/

curlコマンドを実行すると、
output.zipという名前でzip圧縮ファイルが格納されていることが確認できるかと思います。

さらにWebブラウザへ、

http://IPアドレス:8080/

と入力すると名前を付けて保存というメッセージがポップアップで表示され、
保存するとzipファイルがダウンロード出来ているかと思います。

■tar.gzファイル送信用サーバーサイドの実装

次にtar圧縮ファイルを送信するためのコードを載せます。

const fs = require('fs')
const http = require('http');

http.createServer(function(req,res){
    let fileName = "src.tar.gz";
    let contentDip = 'attachment; filename=' + fileName;
    
    res.writeHead(200, {
        'Content-Type': 'application/x-gzip',
        'Content-Disposition' : contentDip
    });
    let readStream = fs.createReadStream(fileName);
    readStream.pipe(res);
}).listen(8080);

先ほどと異なり、レスポンスヘッダには、

res.setHeader('Content-Type', 'application/x-gzip');

とgip圧縮ファイルを転送することを明示しています。
違いはこれだけ!!
後は先ほどのzipファイルと同様です。

確認も先ほどのzipの時と同様のcurlコマンドやWebブラウザで確認できますので動作確認してみてください。

■(補足)他の書き方

補足としてtar圧縮ファイルのレスポンス送信を例に別の書き方も載せておきます。

const fs = require('fs')
const http = require('http');

http.createServer(function(req,res){
    fs.readFile("src.tar.gz", (err,data)=>{
        if(err){
            console.log("err :" + err);
        }else{
            res.setHeader('Content-Type', 'application/x-gzip');
            res.end(data);
        }
    });
}).listen(8080);

こちらのコードでも先ほどまでのコードと同様にtar.gz圧縮ファイルがサーバーから取得することが出来ます。

■最後に

比較的簡単に圧縮ファイルをサーバーサイドからダウンロードすることが出来ました。
もう少し圧縮ファイルの送信方法や使ったアプリなんかを作ってみようかな??



Linux環境にてC++で静的ライブラリ、動的ライブラリを作成する方法に関して

Linux環境で静的ライブラリを作成して運用する機会があったのですが、、
恥ずかしながら今まで静的ライブラリを自作したことがなく、少し困ってしまったので備忘録で残したいと思います。。

今まで実行ファイルは何度も作成しており、静的ライブラリをリンクさせたことはあったのですが、
いざ作成するとなると、、困ってしまった感じです。恥ずかしい。。



■環境

今回手順を記載するのはLinuxとなります。
※題名の通り。

■静的ライブラリ作成手順

早速、静的ライブラリの作成手順を記載します。

ライブラリとして用意するファイルですが、
ファイル名:Calc.cppとし、コードを、

#include <stdio.h>

int Add(int a, int b){
	return a+b;
}

int Sub(int a,int b){
	return a-b;
}

としました。
よくある計算コードですね。

静的ライブラリを作成するためにはオブジェクトファイルが必要になるため、

g++ -c Calc.cpp

でオブジェクトファイルを生成します。

その後、

ar rc Calclib.a Calc.o

のように、arコマンドを用いることで
Calclib.a
のように、静的ライブラリが生成できます。

ライブラリ使用時ですが、こちらはいつも通り、

#include <stdio.h>
int Add(int a, int b);
int Sub(int a,int b);

int main(){
    printf("AddFunc:%d \n", Add(1,2));
    printf("SubFunc:%d \n", Sub(3,1));

    return 0;
}

といったコードを作成の上、

g++ -o calcMain main.cpp Calclib.a

といったようにコンパイルを実行すれば、静的リンクが行われた実行ファイルが作成できます。

こちらの実行ファイルを実行すれば、

AddFunc:3
SubFunc:2

といったように計算結果が返ってくることが確認できます。

Makefileで静的ライブラリを作成

次にMakefileで静的ライブラリを生成するためのコードをご紹介します。
コードはこちら。

NAME	=	Calclib.a
SRCS	=	Calc.cpp
OBJS	=	$(SRCS:.cpp=.o)
CC		=	g++

$(NAME) : $(OBJS)
	ar rc $(NAME) $(OBJS)

all: $(NAME)

.c.o:
	$(CC) -c $< -o $@

clean:
	rm -f $(OBJS) $(NAME)

NAMEに静的ライブラリ名を記載し、SRCSにソースファイル名を記載。
そして、

$(NAME) : $(OBJS)
	ar rc $(NAME) $(OBJS)

にて、ソースファイルをオブジェクトファイルに変換の上、
arコマンドにより、静的ライブラリを作成する。
先ほどのコマンドでの一連の流れを実行しています。

オブジェクトファイル生成は、

.c.o:
	$(CC) -c $< -o $@

にて定義しています。

こちらのMakefileを作成後、

make

を実行すると先ほどのコマンド時と同様にCalclib.aが生成されます。

すでに生成済みの場合、makeコマンド実行しても変化しないので、

make clean

でオブジェクトファイルや静的ライブラリを一旦削除してから試してみてください。

■動的ライブラリ作成手順

補足として動的ライブラリの作成手順に関しても載せておきます。
動的ライブラリの場合には、オブジェクトファイルに対してarコマンドではなく、

g++ -shared -o Calclib.so Calc.o

と-sharedオプションを付与してg++を実行すれば生成できます。

動的リンクは、
>||[
g++ ./Calclib.so
|

とすればOKです。
※動的ライブラリを指定する場合、パスを指定してあげないとうまく読み込んでくれないので注意。

lddコマンドで動的リンクされているか確認することが出来ます。
私の環境ですと、

ldd ./calcMain2

./Calclib.so アドレス

と表示されました。

■動的ライブラリ生成に対するMakefile

静的ライブラリと同様にMakefileを作成していきます。
といっても静的ライブラリの時のMakefileとほぼ同じです。
コードはこちら。

NAME	=	Calclib.so
SRCS	=	Calc.cpp
OBJS	=	$(SRCS:.cpp=.o)
CC		=	g++
CFLAGS	=	-shared

$(NAME) : $(OBJS)
	$(CC) $(CFLAGS) -o $(NAME) $(OBJS)

all: $(NAME)

.c.o:
	$(CC) -c $< -o $@

clean:
	rm -f $(OBJS) $(NAME)

静的ライブラリと異なる点ですが、
・NAMEをCalclib.soとしたこと
・オプション用にCFLAGSを定義したこと
・下記の通り、コードを変更した点

$(NAME) : $(OBJS)
	$(CC) $(CFLAGS) -o $(NAME) $(OBJS)

になります。
こちらは、先ほどコマンドで実行したコードを変数で示して、
オブジェクトファイル生成から動的ライブラリ生成までを記載しているのみです。
後は同じですので割愛します。

■最後に

今回は静的ライブラリや動的ライブラリの生成方法について簡単にまとめました。
初歩のことでも実際にやってみないと分からないことってあるんだな。と感じました。。
色々挑戦していきたいと思います!!



疑似的にパスワード付きtar.gz圧縮ファイルを作成してみる

今回は暗号化技術を用いてtar.gz圧縮させたフォルダにパスワードをかけ、第3者が見れないようにしたいと思います。
ちょっと圧縮ファイルにパスワードを付与しなければならない機会があったのですが、、、
zip化したファイルのパスワードは簡単に見つかったのですが、tarだと見つけるのに苦労しました。。
今後困らないように、備忘録として残しておきたいと思います!!



■環境

環境ですが、今回はraspberryPi 3を用いました。
ただ、Linux OSであれば使える手順になっているかと思います。

■パスワード付きtar.gz圧縮ファイルの作成方法

ではまず、tar.gz圧縮ファイルにパスワードを付与してみたいと思います。

今回例として、tar.gz圧縮ファイル名をhoge.tar.gzとします。
一応、tar.gz圧縮方法のおさらい。
圧縮前のフォルダ名を"hoge"とした場合、tar.gz圧縮は下記コマンドで行えます。

tar -zcv hoge.tar.gz hoge

hoge.tar.gzにパスワードを付与する方法は下記になります。

openssl enc -e -aes-256-cbc -in hoge.tar.gz -out hoge.enc 

上記を実行するとパスワード登録の要求が来るので2回登録したいパスワードを入力すればOK。

実施していることは、openssl enc -eによりtarファイルを暗号化させているのみになります。

もしパスワードをコマンドライン上で登録したい場合には、

openssl enc -e -aes-256-cbc -in hoge.tar.gz -out hoge.enc -pass pass:password

と-passオプションを付与して、パスワードを入力すればOKです。

もしフォルダに対して、暗号化したtar.gzファイルのみを出力させたいのであれば、

tar zcv hoge | openssl enc -e -aes-256-cbc -out hoge.enc-pass pass:password

の通り、パイプラインを用いてtar圧縮⇒openssl暗号化の流れで実行すればOKです。
もしパスワード付き暗号化tar.gzファイルだけが欲しい場合には、
上記を実行すれば中間ファイルであるtar.gz圧縮ファイルが生成されないのでよさそうです。

■パスワード付き暗号化tarファイルを解凍

では先ほどパスワードを付与した暗号化tar.gz圧縮ファイルを解凍してみます。
まず、暗号化したファイルを復号化するには、

openssl enc -aes-256-cbc -d -in hoge.enc -out hoge.tar.gz -pass pass:password

の通り、opensslの復号化を実行すればOKです。
もしtarを解凍したい場合には、

tar -xz hoge.tar.gz hoge

とすればOKですね。

ここで、パスワードを誤って入力すれば、

bad decrypt

とメッセージが出力されます。
hoge.tar.gzは生成されますが、tarを解凍しようとしても解凍できないことも確認できるかと思います。

こちらもパイプラインを用いることで、解凍後のフォルダのみ得ることが出来ます。

openssl enc -aes-256-cbc -d -in hoge.enc -pass pass:password | tar xz

もし上記パイプラインを用いたコマンドで誤ったパスワードを入力すると、

gzip: stdin: not in gzip format
tar: Child died with signal 13
tar: Error is not recoverable: exiting now
error writing output file

といったエラーが出力され、解凍後のフォルダは出力されません。

■補足

今回のコマンドでは、-aes-256-cbcのオプションを付与しています。
こちらは、AES 256形式の暗号化技術を用いて暗号化することを意味しています。

AES暗号化技術は下記に詳しく載っておりますのでこちらを参考にしてください。
qiita.com

■最後に

今回は暗号化・復号化技術を用いて圧縮ファイルにパスワードを付与してみました。
パイプラインで実行すれば中間ファイルを生成せずにパスワード付き圧縮ファイルの生成・解凍が行えるので便利です。



WindowsとLinuxにて再帰的にSHA256でハッシュ値を算出してみる

今回は少し毛色を変えて、SHA256でハッシュ値を求めたいと思います。



■SHA256とは?

SHA256とは、任意の長さの原文から固定長の特徴的な値を算出するハッシュ関数の1つです。
どんな長さの原文からも256bitのハッシュ値を算出することが出来る。

下記に詳しくまとまっておりますので詳細はこちらでご確認ください。
https://wa3.i-3-i.info/word15997.html

LinuxにてSHA256でハッシュ値を求めてみる

ではまずはLinuxWindowsでどのようにSHA256でハッシュ値を求めるのかをまとめます。
と言っても下記コマンドで求めることが可能です!!

sha256sum ファイル名

例えば、test.txtというファイルを作成し、

sha256sum test.txt

と実行すると、

84ced9d1657fbe5989b3e5ad77053f6d62eb478460a2cfb7acf5e39d90650322  test.txt

といった結果が得られます。

さらに、-cオプションを付与することによりハッシュ値比較も行えます。
例えば、

sha256sum test.txt > hoge.txt

と実行し、ハッシュ値hoge.txtに格納した後、

sha256sum -c hoge.txt

と実行すると、

test.txt: 完了

と出力されるかと思います。
"完了"が返ってくると成功、
"失敗"が返ってくるとハッシュ値比較結果NG、
となります。
ですので、sha256sumでハッシュ値を取得した後、test.txtを編集し、

sha256sum -c hoge.txt

を実行すると、

test.txt: 失敗
sha256sum: 警告: 1 個の計算したチェックサムが一致しませんでした

といったメッセージが出力されます。

WindowsにてSHA256でハッシュ値を求めてみる

では次にWindowsでSHA256ハッシュ値を求めてみます。
Windowsではこちらのコマンドになります。

CertUtil -hashfile ファイル名 SHA256

こちらもLinuxと同様にtest.txtで確認してみます。

CertUtil -hashfile test.txt SHA256

を実行すると、

SHA256 ハッシュ (対象 test.txt):
d0f652050ec013d2ca787a8dc8a9c785982839370e6b1e644744dcd51fe2ab7f
CertUtil: -hashfile コマンドは正常に完了しました。

のように、ハッシュ値が返ってくるかと思います。

■フォルダ内ファイルに対して再帰的にハッシュ値を算出する

LinuxWindows共にはSHA256でハッシュ値算出できるのですが、
1つ困ったことがあります。
それは、ファイル名を指定しないとハッシュ値を求めてくれない所です。
例えば、hugaフォルダを作成し、その配下にhuga2フォルダを作成し、huga2フォルダにtest.txtを移動させた場合、
要するに、

huga/huga2/test.txt

の構成に対して、

sha256sum huga/*

を実行しても、

sha256sum: huga/huga2: ディレクトリです

と出力されてしまいます。
これは、Windowsにも同様に発生します。

このため、
フォルダ内のファイル・フォルダに対して再帰的に処理を実行することが必要になる。
ということです。

LinuxWindowsのそれぞれで再帰的にSHA256を処理するためのコマンドはこちらになります。

Linux

find huga -type f -exec sha256sum -b {} \;

Windows

cd huga
for /r %i in (*) do (CertUtil -hashfile "%i" SHA256)

こちらを実行するとそれぞれ、
Linux

e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 *huga/huga2/test.txt

Windows

17e682f060b5f8e47ea04c5c4855908b0a5ad612022260fe50e11ecb0cc0ab76
CertUtil: -hashfile コマンドは正常に完了しました。

尚、SHA256のハッシュ値算出結果をテキストに書き込むには、

Linux

find huga -type f -exec sha256sum -b {} \; > hoge.txt

Windows

cd huga
for /r %i in (*) do (CertUtil -hashfile "%i") >> hoge.txt

とすればOKです。

また、LinuxでのSHA256のハッシュ値比較ですが、今回のケースでも、

sha256sum -c hoge.txt

とすればOKです。

Windowsでの注意点

CertUtil -hashfile ファイル名 SHA256

ですが、空ファイル(新規作成しただけ)に対して実行すると、

CertUtil: ファイルを格納しているボリュームが外部的に変更されたため、開かれているファイルが無効になりました。

といったエラーが返ってきてしまいます。

■最後に

今回はハッシュ値算出方法に関してまとめてみました。
ハッシュ値を求めたり、比較したりするだけであれば簡単に実行出来ることが分かったのが収穫。