技術メモ

役に立てる技術的な何か、時々自分用の覚書。幅広く色々なことに興味があります。

ASP, Saas, Paas, Iaas, Daasの具体例を挙げてみる。活用方法など。

クラウドの分類として用いられるSaas…etcなどの分類、言葉だけ聞くとあまりピンとこない。
実例を挙げることでイメージしやすくしてみた。
f:id:swdrsker:20180202042259p:plain*1

ASP, Saas

ASPはアプリケーションソフトの機能をネットワーク経由で顧客にサービスとして提供することであり、それを行っている事業者である。通常、利用者はブラウザソフトなどを使用してインターネットなどのネットワークを経由し、遠隔地からASPのサーバにアクセスすることで、そのサーバ内に格納された各種アプリケーションソフトの機能をサービスの形で利用する。
wikipedia: アプリケーションサービスプロバイダ

SaaS(サース、Software as a Service)は、必要な機能を必要な分だけサービスとして利用できるようにしたソフトウェア(主にアプリケーションソフトウェア)もしくはその提供形態のこと。一般にはインターネット経由で必要な機能を利用する仕組みで、シングルシステム・マルチテナント方式になっているものを指す
wikipedia: Saas

ASPSaasって何が違う?

説明を読むと、ん?何が違うの?って感じが、厳密な違いはないらしい。
ASPは事業者やビジネスモデルとしての意味合いが強く、Saasはサービスにフォーカスした言葉というニュアンスの違いだという。

具体例

Webブラウザ上で使うサービスは大体(全て?)Saasに当てはまる。

Paas

PaaSでは、ソフトウェアを構築および稼動させるための土台となるプラットフォームを、インターネット経由のサービスとして提供する。開発者は、プラットフォーム上で構築したサービスを自分の顧客に提供することができる。 具体的には、インフラ、DBMSユーザインタフェースなどのシステム開発手段となるツールや、開発したシステムを運用するための環境をインターネットを通じて「サービス」として提供し、月額使用料などの形で収入を得る事業モデルである
wikipedia: Paas

Iaas (Haas)

IaaS(Infrastructure as a Service の略。インターネットを利用したコンピュータの利用形態である。IaaSでは、コンピュータシステムを構築および稼動させるための基盤(仮想マシンやネットワークなどのインフラ)そのものを、インターネット経由のサービスとして提供する。
wikipedia: Iaas

Daas

DaaS は、Desktop as a Serviceの略で、その言葉のとおり個人用のデスクトップ環境をクラウド上に構築し、ネットワーク越しにその環境を呼び出して利用することを提供するサービスです。基本ソフトをはじめ全てのソフトやデータがネットワーク上のサーバーにあります。ユーザの端末は画面を表示する機能とキーボードなど操作に必要な機能だけあればよく、OSやアプリケーションソフトなどはすべてサーバ上で動作します。
DaaS(Desktop as a Service) | IoT

活用方法など【中級者以上向け】

この記事は面白い。

特に最近は人工知能ブームで機械学習や統計解析が盛んにおこなわれているが、その中で使うIoTでリアルタイムなデータを取ってきたりGPUAPIなんかを使いたい時にIaasやPaasを使うようだ。
データの管理やプログラムだけに集中したい時に重宝される。
経験上少し昔はそういった分析業務におけるクラウドAWS一強だった感じだが、Azureもそれなりに使われているらしい。

pythonでコードを書きながら楕円曲線暗号を理解する

仮想通貨についての勉強
楕円曲線暗号とは、ビットコインのデジタル署名で使われてる公開鍵暗号方式

この記事にあるコードを写経しながら勉強する。

自分自身まだ深く理解してないところがあるので解説は別の機会に書くことにしてメモ書き程度にとどめておく。

コード

from hashlib import sha256

class ECDSA:
    def __init__(self):
        # parameters are based on SPEC256k1
        self.cp = pow(2,256) - pow(2,32) - pow(2,9) - pow(2,8) - pow(2,7) - pow(2,6) - pow(2,4) - pow(2,0)
        self.cb = 7
        self.ca = 0
        self.base_x = 55066263022277343669578718895168534326250603453777594175500187360389116729240
        self.base_y = 32670510020758816978083085130507043184471273380659243275938904335757337482424
        self.base = (self.base_x, self.base_y)
        self.secret_key = None
        self.public_key = None

    def generate_key(self, string):
        secret_hash = sha256(string.encode('utf-8')).hexdigest()
        secret_key = int(secret_hash, 16)
        pt = self.EC_multi(secret_key)
        public_key = int("04" + "%064x" % pt[0] + "%064x" % pt[1], 16)
        self.secret_key = secret_key
        self.public_key = public_key
        return (public_key, secret_key)

    def EC_add(self, P, Q):
        lam = ((Q[1] - P[1]) * inv_mod(Q[0] - P[0], self.cp)) % self.cp
        x = ((pow(lam, 2)) - P[0] - Q[0]) % self.cp
        y = (lam * (P[0]- x) - P[1]) % self.cp
        return (x,y)

    def EC_double(self, P):
        lam = ((3 * (pow(P[0], 2) + self.ca) * inv_mod(2 * P[1], self.cp))) % self.cp
        x = (pow(lam, 2) - 2*P[0]) % self.cp
        y = (lam * (P[0] - x) - P[1]) % self.cp
        return (x,y)

    def EC_multi(self, scalar):
        if scalar == 0:
            raise ValueError('invalid scalar/ purivate key')
        scalar_bin = str(bin(scalar))[2:]
        point = self.base
        for i in range(1, len(scalar_bin)):
            point = self.EC_double(point)
            if scalar_bin[i] == "1":
                point = self.EC_add(point, self.base)
        return point

def inv_mod(k, mod):
    return pow(k, mod-2, mod)


if __name__=="__main__":
    ecdsa = ECDSA()
    pk, sk = ecdsa.generate_key("Satoshi Nakamoto")
    print(sk)
    print(pk)

(補足)モジュラ逆数

モジュラ逆数とはa^{-1}\equiv x \pmod{m}となるxのこと。
素数 mと互いに素な aに対して

 a^{-1}\equiv a^{m-2} \pmod{m}

となることを使っている。

(証明)
オイラー関数 \phi(m)を用いて、mが素数の時
\displaystyle
\left\{
\begin{array}{1}
 a^{\phi(m)}\equiv 1 \pmod{m}\\
 \phi(m) = m-1 
\end{array}
\right .
なので

a^{\phi(m) - 1} \equiv a^{-1} \pmod{m} \\
a^{m-2} \equiv a^{-1} \pmod{m}
(Q.E.D)

pythonでは a^{m-2}\pmod{m}

pow(a, m-2, m)

の1行で書ける

参考にしている本

仮想通貨の教科書

仮想通貨の教科書

pythonでコードを書きながらデジタル署名を理解する

仮想通貨の仕組みについての勉強の続き。
仮想通貨にはなくてはならないデジタル署名を実装して勉強した。
デジタル署名自体は目新しいものではなく昔からある技術で、今でもネット決済など広く使われている。

デジタル署名とは

ザックリとした説明

デジタル署名とは、その名の通り文書に「署名」すること。(ここでいう文書とは文字列や数字列といったデータのこと)
では署名に必要な要件とは何か。

  • 第一に、署名をすることができるのは署名者(アリスとする)だけだが、署名を見た人は誰でもそれが有効であることが確認できなければいけない。
  • 第二に、署名と文書は密接に結びついており、別の文書に対するアリスの同意、保証を示すためには使えない。つまり色々な署名からアリスの署名の仕方を推測すること(本当の署名でいうところの筆跡など真似に相当するような行為)、はできないということ。

という2つの要件が必要になってくる。

踏み込んだ説明

暗号理論を使えば上の条件が実現できる。
公開鍵暗号を用いる方法だ。(公開鍵暗号については RSA暗号を実装してみる(知識編) - 技術メモ
具体的にはデジタル署名には3つのスキームで成り立つ。

  • 公開鍵と秘密鍵のペアを生成する (generateKey)
  • 秘密鍵を使って文書に対する署名を生成する (sign)
  • 公開鍵・文書をつかって署名が正しいものかどうかを検証する (verify)

署名者(アリスとする)はgenerateKeyを使って秘密鍵skと公開鍵pkを生成し、公開鍵を公開する。
アリスは署名したい文書Dataをハッシュ関数にかけたうえで秘密鍵skを使って署名signatureを生成する。
承認者は公開されている公開鍵pk・文書Data・アリスから受け取った署名signatureを使って、pk,Data,signatureの組が正当であればTrueを返し違っていればFalseを返す。署名が間違っているか文書が書き換えられていれば承認がうまくいかないことになる。
f:id:swdrsker:20180124031957p:plain

デジタル署名に対する攻撃

N通りの{文書、署名}および公開鍵の組み合わせから秘密鍵を見破ることができればデジタル署名は破られてしまう。(chosen message attack)
だが、現在一般に使われている署名方式ではこれを行うのはほぼ不可能に近い。

コード

python (python3.5)で書いた。RSAハッシュ関数(SHA256)など暗号技術諸々はpycryptoを使った。
ちなみに実際のビットコインでは公開鍵暗号方式RSAではなく楕円曲線暗号が使われている。

digitalsignature.pyという名前で保存

from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from base64 import b64decode, b64encode
import sys

def generate_key(keysize=2048, passphrase = None):
    new_key = RSA.generate(keysize)
    public_key = new_key.publickey().exportKey()
    secret_key = new_key.exportKey(passphrase = passphrase)
    return secret_key, public_key

def sign(secret_key, data, passphrase = None):
    try:
        rsakey = RSA.importKey(secret_key, passphrase = passphrase)
    except ValueError as e:
        print(e)
        sys.exit(1)
    signer = PKCS1_v1_5.new(rsakey)
    digest = SHA256.new()
    digest.update(b64decode(data))
    sign = signer.sign(digest)
    return b64encode(sign)

def verify(pub_key, signature, data):
    rsakey = RSA.importKey(pub_key)
    signer = PKCS1_v1_5.new(rsakey)
    digest = SHA256.new()
    digest.update(b64decode(data))
    if signer.verify(digest, b64decode(signature)):
        return True
    else:
        return False
テスト

digitalsignature.pyと同じフォルダ内で実行

from digitalsignature import *

# 秘密鍵と公開鍵を作る。(パスワードはなくても良い)
password = "password"
sk, pk = generate_key(passphrase = password)

# メッセージに署名する(署名者が行う)
message = "hoge"
sig = sign(sk, message, passphrase = password)

# 承認テスト(承認者が行う)
if verify(pk, sig, message):
    print("承認 OK")
else:
    print("承認 NG")

# メッセージの書き換えに対するテスト
changed_message = "hogehoge"
if verify(pk, sig, changed_message):
    print("書き換えテスト NG")
else:
    print("書き換えテスト OK") # 承認されなければOK

# 間違った秘密鍵の署名に対するテスト
sk2, pk2 = generate_key(passphrase = password)
sig2 = sign(sk2, message, passphrase = password)
if verify(pk, sig2, message):
    print("不正署名テスト NG")
else:
    print("不正署名テスト OK") # 承認されなければOK
  • 実行結果
承認 OK
書き換えテスト OK
不正署名テスト OK

参考にした本

仮想通貨の教科書

仮想通貨の教科書