2024年9月
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          
無料ブログはココログ

 

2022年1月23日 (日)

ユニットテストについて

ウチのチームでユニットテストレベルの不具合が摘出されておらず、システムテスト終わりに見つかってしまうという問題が発生している。
そこで、ユニットテストの考え方を書き出してみる。

  • ユニットテストの目的は、詳細設計書(クラス・関数についての設計書)の仕様を満たしているか動作確認を行う事。
  • 詳細設計書は、関数についての仕様を記述してある。入力に対してなにがしか処理を行った結果、出力を行うのが関数の役割。
    入力値に対して出力値を確認するのが、ブラックボックステスト。
    関数内の分岐を考慮して、そのケースを確認するのがホワイトボックステスト。if文の条件式で真偽値となるケースを確認するとか。
  • テストの指標としてカバレッジ(網羅性)がある。C0/C1/C2=命令網羅/分岐網羅/条件網羅。
    目指したいのは分岐条件の条件式毎の確認を行う条件網羅。(if(A==1 && B==2) とあったら、Aが1、1以外×Bが2、2以外の4パターンを確認する)
    • 条件網羅は、条件式が多くなると組み合わせが爆発的に多くなり、工数が膨らむ。
      項目数を減らす考え方にAll-Pair法(ペアワイズ法)がある。関数の引数が複数ある場合、引数2つ一組で見てその値の組み合わせがテスト項目のどこかで出現されるようにするもの。全組み合わせではなく2引数の組み合わせというところがミソ。2引数の組み合わせで7・8割は問題を摘出できるという統計から求めたブラックボックス的手法。
      • 引数:A,B,C,Dがそれぞれ0~2の値をとる場合、AB,AC,AD,BC,BD,CD の組み合わせに対して、2引数が取りうる組み合わせ00,01,02,10,11,12,20,21,22 を、ABCDで組み合わせる。
        すると、以下の9通りに収束できる。
        A B C D
        0 0 0 0
        0 1 1 1
        0 2 2 2
        1 0 2 1
        1 1 0 2
        1 2 1 0
        2 0 1 2
        2 1 2 0
        2 2 0 1

        上記は9パターンであるが、全パターンを組み合わせると3^4=81パターン必要となる。
        全て確認してコストに見合うかどうかという話。
        件数を減らすにも、根拠と理由を持って必要がある。

  • ユニットテストは関数を対象とした物なので、関数内の処理が複雑になるほどテストも複雑になる。
    よって、複雑なチェック条件は一つの関数に入れるのではなく、別の判定関数に切り出す。その判定関数を使用する所は真偽を確認するだけでよくなる。
  • 既存関数の修正を行うときに、正常に動いている所を修正するのは怖い事(動いている物は、触らなければそのまま動く」という考え)ではあるが、修正するのはもう仕様が変わってしまって、それは正しく動かないことなので(だから修正する)わかりやすく書き換える方が保守性を考慮すると今後の修正コストが下がる。怖いのは分るが、だからテストを正しく行って確認する。
  • ユニットテストがやりやすくなる関数を作る事。これは、単純なテストデータで、ユニットテストが出来る事を目指せば良い。
    つまり、関数を作ってテストを作るのでは無く、テストを考えて関数を(分割して)作る事を考える。(動く関数を作ってから分割するでもよいか)

★テストは品質を上げる作業ではなく、品質が悪い所とその傾向を洗い出すための作業です。
→テストの結果を受けて、どこにどの様な問題が多いか、どうしてそのような問題を起こしたかを確認し、その問題の傾向から品質向上施策を考えてバグを潰していきます。

★テストはただ実行するものではありません。
 ・入力値→[処理]→出力値[結果]を確認するものです。
 ・処理を実行して落ちなければいいという物ではありません。入力値に対応する結果を確認してください!
 ・入力値は、条件を分岐する全てのケースを確認してください、if文の分岐を通ればいい物ではありません!

2021年7月11日 (日)

覚書「サロゲートペア」について

「サロゲートペア」とは、UNICODEの有る範囲の文字列群(U+100000 ~ U+10FFFF)をUTF-16では一文字分では表記できないため、二文字分を使用する、その範囲の文字列群のことを指す。
なので、UTF-8やUTF-32には、サロゲートペアという概念はない。UTF-16のサロゲートペアの範囲に当たるUNICODEの文字列群は当然UTF-8やUTF-32で扱えるけど、それはサロゲートペアで扱っていない(そのような仕組みではない)。

簡単にサロゲートペアの範囲の文字をファイルに出力するプログラム(C++)を書いてみた。

#include <iostream>
#include <array>
#include <string>

std::wstring convertUicodeToUTF16(char32_t code)
{
	char16_t h = 0xd800;
	char16_t l = 0xdc00;

	code -= 0x10000;
	h += (code / 0x400) % 0xffff;
	l += code % 0x400;
	std::wstring result;
	result.push_back(h);
	result.push_back(l);

	return result;
}

int main()
{
	FILE* f = 0;
	errno_t eno = fopen_s(&f, "UTF16.txt", "wb");
	if (eno != 0) {
		fprintf_s(stderr, "ERR:fopen : eno=%d\r\n", eno);
		return -1;
	}

	// BOM UNICODE(BE)
	char bom[] = { 0xff, 0xfe };
	fwrite(bom, sizeof(bom), 1, f);

	uint16_t cnt = 0;
	//for (char32_t code = 0; code <= 0x10FFFF; code++) {
	for (char32_t code = 0x10000; code <= 0x10FFFF; code++) {

		if (cnt == 0) {
			fwprintf(f, L"%08x\t", code);
		}
		std::wstring result;
		if (code < 0x10000) {
			result.push_back((wchar_t)code);
		}
		else {
			result = convertUicodeToUTF16(code);
		}

		fwrite(result.c_str(), result.length() * sizeof(wchar_t), 1, f);

		cnt++;
		if (cnt == 0x40) {
			fwprintf(f, L"\r\n");
			cnt = 0;
		}
	}

	fclose(f);

	return 0;
}


・文字が割り振られていない範囲も出力している。
・0x40文字単位で改行を入れているのは、改行なしで出力したファイルをエディタで開くとスクロールできなくなっちゃうから。
↓出力される内容はこんな感じ(2行のみ出してみた)。


00010300 𐌀𐌁𐌂𐌃𐌄𐌅𐌆𐌇𐌈𐌉𐌊𐌋𐌌𐌍𐌎𐌏𐌐𐌑𐌒𐌓𐌔𐌕𐌖𐌗𐌘𐌙𐌚𐌛𐌜𐌝𐌞𐌟𐌠𐌡𐌢𐌣𐌤𐌥𐌦𐌧𐌨𐌩𐌪𐌫𐌬𐌭𐌮𐌯𐌰𐌱𐌲𐌳𐌴𐌵𐌶𐌷𐌸𐌹𐌺𐌻𐌼𐌽𐌾𐌿
00010340 𐍀𐍁𐍂𐍃𐍄𐍅𐍆𐍇𐍈𐍉𐍊𐍋𐍌𐍍𐍎𐍏𐍐𐍑𐍒𐍓𐍔𐍕𐍖𐍗𐍘𐍙𐍚𐍛𐍜𐍝𐍞𐍟𐍠𐍡𐍢𐍣𐍤𐍥𐍦𐍧𐍨𐍩𐍪𐍫𐍬𐍭𐍮𐍯𐍰𐍱𐍲𐍳𐍴𐍵𐍶𐍷𐍸𐍹𐍺𐍻𐍼𐍽𐍾𐍿
・・・

2020年4月19日 (日)

[Powershell]画像サイズ変更ツール imageConverter

githubに上げたものを転載

 

これは何?

このツールは、指定したフォルダ内にある(複数の)画像ファイルに対して、一括してサイズ変更とフォーマットの変更を行います。みんな大好きPowershellです。

ブログに乗せる写真を今までは手作業でチマチマgimpを使ってサイズを変換していたのですが、メンドクサイので一括変換しようと作ってみました。

入力・出力で扱える画像フォーマットは、System.Drawing.Bitmapで読み書きできるモノになります。現状、jpeg,bmp,exif,gif,icon,png,tiff,wmf。

Powershellでの画像の取り扱いについては、Qiita 「PowerShell で画像の回転、リサイズを行う」を参考にしました。@miyamiyaさん、ありがとう!

使い方

PS > .\imgConverter.ps1 -path C:\Users\UserName\Pictures -l 800 -s 600 -mode Jpeg

  • -path 画像ファイルを格納したフォルダパス
  • -l (long side)長辺のPixel数
  • -s (short side)短辺のPixel数[省略可] 省略時は0
  • -imgf (image format)変換する画像フォーマット名 jpeg,bmp,exif,gif,ico,png,tiff,wmf [省略可] 省略時はjpeg

省略可能な引数を省略したとき

PS > .\imgConverter.ps1 -path C:\Users\UserName\Pictures -l 800

仕様

  • -pathについて
    指定したフォルダにある画像ファイルを全て変換します。
    画像として読み込めないファイルがある場合は、"Convert ERROR."とエラー表示して変換しません。
    存在しないパスを指定した場合は、引数エラーになります。
  • -l、-sについて
    サイズ変換は元画像の縦横の長い方を "-l" で指定したPixel数に、短い方を "-s" で指定したPixel数に設定します。例えば "-l 800 -s 400" としたとき、1200 × 900 の画像は 800 × 400 に、900 × 1200の画像は 400 × 800 に変換されます。つまり長いほうが800Pixel、短いほうが400Pixelになります。
    "-l"に0以下の値を指定した場合、引数エラーになります。
  • -sを省略、または0を指定した場合は、元画像のサイズの比率を維持して、長いほうを-lで指定したPixel数に変換します。例えば "-l 800" としたとき、1200 × 900(4:3の比)の画像は 800 × 600 に、900 × 1200(3:4の比)の画像は 600 × 800 に変換されます。
  • -imgfについて
    画像フォーマットを指定します。設定可能な値は、jpeg,bmp,exif,gif,ico,png,tiff,wmfになります。これらの文字列のいずれかを設定してください。
    これら以外の文字列を指定した場合、引数エラーになります。
  • 出力ファイル名は、-pathで指定されたフォルダに、ファイル名<拡張子無し>_.<-imgfで指定した文字列> となります。
    C:\Users\UserName\Pictures\xxx.jpg を bitmapに変換した場合、C:\Users\UserName\Pictures\xxx\_.bmp になります。

実行結果例

PS > .\imagConverter.ps1 -path C:\Users\UserName\Pictures -l 800
C:\Users\UserName\Pictures\xxx_.jpeg:(3264,2448)->(800,600)
C:\Users\UserName\Pictures\yyy_.jpeg:(5184,3888)->(800,600)

プログラム


param(
[parameter(mandatory)][string]$path,
[parameter(mandatory)][int]$l,
[int]$s,
[string]$imgf="jpeg"
)
[void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")

$imgFList
=@{ jpeg=[System.Drawing.Imaging.ImageFormat]::Jpeg;
bmp=[System.Drawing.Imaging.ImageFormat]::Bmp;
exif=[System.Drawing.Imaging.ImageFormat]::Exif;
gif=[System.Drawing.Imaging.ImageFormat]::Gif;
ico=[System.Drawing.Imaging.ImageFormat]::Icon;
png=[System.Drawing.Imaging.ImageFormat]::Png;
tiff=[System.Drawing.Imaging.ImageFormat]::Tiff;
wmf=[System.Drawing.Imaging.ImageFormat]::Wmf;
}
if (-not (Test-Path $path)) {
write-error "Invalid argment `"path`"."
return
}
if ($l -le 0) {
write-error "Invalid argment `"l`"."
return
}
if (!$imgFList.ContainsKey($imgf)) {
write-error "Invalid argment `"imgf`"."
return
}
$imageFormat=$imgFList[$imgf]

get-childitem $path | ?{!$_.PSIsContainer} | %{
try {
$image = New-Object System.Drawing.Bitmap($_.fullname)
if ($image.Height -lt $image.Width) {
# 縦 < 横 -> 横が長い
$w=$l
if ($s -eq 0) {
$h=[math]::Truncate(($w/$image.Width)*$image.Height+.5)
} else {
$h=$s
}
} else {
$h=$l
if ($s -eq 0) {
$w=[math]::Truncate(($h/$image.Height)*$image.Width+.5)
} else {
$w=$s
}
}
$canvas = New-Object System.Drawing.Bitmap($w, $h)
$graphics = [System.Drawing.Graphics]::FromImage($canvas)
$graphics.DrawImage($image, (New-Object System.Drawing.Rectangle(0, 0, $canvas.Width, $canvas.Height)))
$outname=("{0}\{1}_.{2}" -F $_.DirectoryName, $_.basename, $imgf)
("{0}:({1},{2})->({3},{4}) " -F $outname, $image.Width, $image.Height, $w, $h)
$canvas.Save($outname, $imageFormat)
} catch {
write-error ("Convert ERROR. {0}" -F $_.fullname)
} finally {
if ($graphics -ne $null) { $graphics.Dispose() }
if ($canvas -ne $null) { $canvas.Dispose() }
if ($image -ne $null) { $image.Dispose() }
}
}

2019年5月26日 (日)

PKCS#12形式ファイルを使ってXML文書に署名付与したり、署名検証したり

PKCS#12(拡張子.p12のファイル)を使ってXML文書にXML署名(Enveloped署名)を行うのと署名検証するプログラムをC#で作ってみた。

  • 基本、SignedXmlクラスに載っているコードを使った。(2つあるけど、上の方は署名の公開鍵を埋め込まない。下の方はRSAKeyValueを埋め込んでいる)
    でも、このコードは、証明書(RSA)を生成してそれをKeyInfo要素にRSAKeyValue要素が設定する。
    PKCS#12形式ファイルを読み込んで使いたいし、x509Certificate要素を入れたい。
  • PKCS#12形式ファイルのprivateKeyを取り出すには、手順がある。
    • PKCS#12ファイルを、new X509Certificate2(<filename>, <password>, X509KeyStorageFlags.Exportable);で読み込む。
    • そのx509からprivateKeyを取り出すには、(RSACryptoServiceProvider)x509.PrivateKey;とやる。
      この使おうとするとsignedXml.ComputeSignature()で「無効なアルゴリズムが指定されました」例外になってしまう・・・。PersistKeyInCspがtrueの所為?
    • 上記の例外を回避するには、別のRSACryptoServiceProvider()インスタンスに対して、ImportParameters(privateKey.ExportParameters(true));とやって、先ほどのprivateKeyを食わせる。するとPersistKeyInCspがfalseになっているね。
  • KeyInfo要素にRSAKeyValue要素が入るのは、keyInfo.AddClause(new RSAKeyValue((RSA)Key));とやっている。
    x509Certificate要素を入れるのには、keyInfo.AddClause(new KeyInfoX509Data(x509));とやる。

●引数: 

  • 第1引数:PKCS#12ファイル
  • 第2引数:PKCS#12ファイルのパスワード
  • 第3引数:署名を付与するXML文書
  • 第4引数:署名を付与する要素(id属性の値を設定)
  • 第5引数:出力する署名済XML文書
C:\test>VerfySignedXML.exe my-identity.p12 test test.xml xxxx test_signed.xml
The XML signature is valid.

 

 
●署名対象のXML : test.xml <?xml version="1.0" encoding="utf-8" ?> <root> <creditcard id="xxxx"> <number>19834209</number> <expiry>02/02/2002</expiry> </creditcard> </root>

 

●署名付与したXML : test_signed.xml
<?xml version="1.0" encoding="utf-8"?>
<root>
    <creditcard id="xxxx">
        <number>19834209</number>
        <expiry>02/02/2002</expiry>
    </creditcard>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /><Reference URI="#xxxx"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /></Transforms><DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /><DigestValue>7WFHBFyOfyEEGK6n7OHvdA6K345HSlAVwPFaEWgXcX0=</DigestValue></Reference></SignedInfo><SignatureValue>JWPhDDxFQalUmtWPdd8o55To3p5RI7TJvnXz79H2tb60J4B1lg4TeTvTOtHZuiJJpHZMeNyuARtwNRX+etDr9j4UmXdUJ/CXvxJFXajoYXRwTGYK6i/RF0QDeoOexSFYrK+JZeHrUV6T7UMU6O5ZxrmuU+c7U7Ki0dlHypdjQac=</SignatureValue><KeyInfo><X509Data><X509Certificate>MIIClTCCAf4CCQCBK5YXcZkuqjANBgkqhkiG9w0BAQsFADCBjjELMAkGA1UEBhMCSlAxETAPBgNVBAgMCEtBTkFHQVdBMREwDwYDVQQHDAhZT0tPU1VLQTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlLT1RBVFVJTlUxIjAgBgkqhkiG9w0BCQEWE2tvdGF0dWludUBuaWZ0eS5jb20wHhcNMTcxMjA5MTE1NTQ3WhcNMjcxMjA3MTE1NTQ3WjCBjjELMAkGA1UEBhMCSlAxETAPBgNVBAgMCEtBTkFHQVdBMREwDwYDVQQHDAhZT0tPU1VLQTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlLT1RBVFVJTlUxIjAgBgkqhkiG9w0BCQEWE2tvdGF0dWludUBuaWZ0eS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMPnNgYbe5x2xJyEshyH768ZU8Un5e5j5uKsihiTOya9wAdxNJeWINB21zXe+mjKxnOsmATPdGZ0DH82xqz+2mX//JKqwDMsG8nMacUI4BiCvYGvlTyxWkRQw3LKU2ufQQ+GYboypwQE51X3S+rRDLGoLuG0BtRooAvah1adJfhdAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAClBDgTCsbe19+CYomJC0PciFw/tvk6/TiC6VSNuQmFg61KrTaU4XFmj/u8qbD8ESyXaJKavcZmjWhKk6F6JSx9YYBz0b1dXz/9l0po6AwUooDk3yp5NtRGiErAcM6MCZ5LPM9+255hMa3fxX26Y7xpPxH84jv6j2fiYcsdYknaQ=</X509Certificate></X509Data></KeyInfo></Signature></root>
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.Xml;

public class VerifySignedXML
{
    // 引数
    //  1:PKCS12ファイル
    //  2:パスワード
    //  3:署名前XMLファイル(入力)
    //  4:署名付与対象(ID属性の値)
    //  5:署名済XMLファイル(出力)
    public static void Main(String[] args)
    {
        if (args.Length != 5)
        {
            return;
        }
        sign(args[0], args[1], args[2], args[3], args[4]);
        verfy(args[4]);
    }

    public static void sign(String filename, string password, string xmlFilename, string id, string signedXmlFilename)
    {
        try
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load(xmlFilename);
            XmlNodeList list = xmlDoc.SelectNodes(string.Format(@"//*[@id='{0}']", id));
            if (list.Count == 0)
            {
                return;
            }

            X509Certificate2 x509 = new X509Certificate2(filename, password, X509KeyStorageFlags.Exportable);
            SignXml(xmlDoc, x509, id);
            xmlDoc.Save(signedXmlFilename);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    public static void SignXml(XmlDocument xmlDoc, X509Certificate2 x509, string uri)
    {
        if (xmlDoc == null)
        {
            throw new ArgumentException("xmlDoc");
        }
        if (x509 == null)
        {
            throw new ArgumentException("x509");
        }

        SignedXml signedXml = new SignedXml(xmlDoc);

        RSACryptoServiceProvider privateKey = (RSACryptoServiceProvider)x509.PrivateKey;
        RSACryptoServiceProvider privateKey1 = new RSACryptoServiceProvider();
        privateKey1.ImportParameters(privateKey.ExportParameters(true));
        signedXml.SigningKey = privateKey1;

        Reference reference = new Reference();
        reference.Uri = "#" + uri;

        XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
        reference.AddTransform(env);

        signedXml.AddReference(reference);

        KeyInfo keyInfo = new KeyInfo();
        keyInfo.AddClause(new KeyInfoX509Data(x509));
        signedXml.KeyInfo = keyInfo;

        signedXml.ComputeSignature();

        XmlElement xmlDigitalSignature = signedXml.GetXml();

        xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));

    }

    public static void verfy(string signedXmlFilename)
    {
        try
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load(signedXmlFilename);

            bool result = VerifyXml(xmlDoc);
            if (result)
            {
                Console.WriteLine("The XML signature is valid.");
            }
            else
            {
                Console.WriteLine("The XML signature is not valid.");
            }

        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    public static Boolean VerifyXml(XmlDocument Doc)
    {
        SignedXml signedXml = new SignedXml(Doc);
        XmlNodeList nodeList = Doc.GetElementsByTagName("Signature");

        if (nodeList.Count <= 0)
        {
            throw new CryptographicException("Verification failed: No Signature was found in the document.");
        }
        if (nodeList.Count >= 2)
        {
            throw new CryptographicException("Verification failed: More that one signature was found for the document.");
        }

        signedXml.LoadXml((XmlElement)nodeList[0]);
        return signedXml.CheckSignature();
    }
}

2019年5月 3日 (金)

WebRequest()で訳が分からない例外が発生したけど

C#なりPowershellなりで、cocolog(@nifty)のログイン画面(http://www.cocolog-nifty.com/t/sso/start)をWebRequestクラスを使って読み込もうとして、System.Net.HttpWebRequest.GetResponse()を実行したとき、何故かSystem.Net.WebException例外が発生する。

Messageは、"An error occurred while sending the request. The server returned an invalid or unrecognized response."となっていて、理解不能。

訳が分からんなーとさんざん悩んだんだけど(HTTPstatus=302でRedirectしているし、そこら辺かなと思ったけどAllowAutoRedirectプロパティはデフォルトでtrueだしーとか)、結局はUserAgentプロパティに何も設定していなくて、WebServerにお前ナニモンじゃとはじかれたもよう?
FireFoxの開発者モードで確認したUserAgentの内容を設定してみたら通った。

 
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.cocolog-nifty.com/t/sso/start");
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();

 

2019年4月30日 (火)

Powershellでココログの記事をExportするプログラム

現状、ココログでは、記事の内容をExportすることができません。
というわけで、一身上の都合(※)で、ココログに投稿されている全記事の内容(タイトル、本文・追記、カテゴリ)を出力するPowershellプログラムを作ってみました。

※:Amazonから”アソシエイトプログラムで1年間だれも買わなかったから垢バンするのでリンクを全て消せ”という横暴なことを通知されたので、このブログの内容を一旦保存して、それからリンクを消す方法を模索してみようかと思っている次第であります。

■仕様

  • ココログの記事編集画面にログイン→記事一覧を取得→記事一覧のリンクから記事投降画面に遷移して内容(タイトル、本文・追記、カテゴリ)を取得しJSONファイルに出力する。
    なので、ココログに投稿できる自分のブログしか、取得できません。
  • 出力するファイル名は、記事一覧のリンクにあるパスの最後尾=記事IDとタイトルを組み合わせて、"<記事ID>_<タイトル>.json"というフォーマットになります。ファイル名に使用できない文字("<>|:*?\/\r\n[])は、アンダーバー"_"に置き換えます。
  • タイトル、本文、追記、カテゴリのキーは、その画面のHTML中の該当要素にあるid属性の値を使っています。例えば以下のようになります。(記事IDが先頭にあるので、記事ごとにキーが変わります)
    • タイトル:126006900__entry_title
    • 本文:126006900__entry_text
    • 追記:126006900__entry_text_more
    • カテゴリ:126006900__category_ids
  • 記事一覧100ページ、2,985記事を取得するのに40分くらいかかります。ウェイトは入れていません。

■技術的なこと

  • Webページを取得するのに、Invoke-WebRequestコマンドを使っています。Cookieを使ってトップ画面から画面遷移が必要。
  • 基本的には、リンクを踏んで移動。ログインだけがPOST。
  • 記事の内容を取得するのに、記事投降画面のHTMLから正規表現を使用。ParsedHTMLからタグを指定して要素を取得したほうが、確実化と思われましたが、要素取得getElementsByTagName()が同じ画面でも取得するたびに不定期にNotSupportExceptionとなる現象が発生。正常に取得できた時とエラーになるときとHTMLを比較してみると属性の順番が異なっているのは確認できたが、内容がおかしいようには見えない・・・。しょうがないので文字列として扱う、つまり正規表現で検索する方が安定。
# cocolog start page
write-host "** cocolog start page"
$resp = Invoke-WebRequest "http://www.cocolog-nifty.com/" -SessionVariable "session"
if($resp.StatusCode -ne 200) { exit; }
# cocolog start page→login page
write-host "** cocolog start page->login page"
$resp = $null
$resp = Invoke-WebRequest "http://www.cocolog-nifty.com/t/sso/start" -WebSession $session
if($resp.StatusCode -ne 200) { exit; }
do {
# login実行→ブログトップページ
#input UID/PDW
try {
$cr = Get-Credential
} catch {
exit;
}
$link = "https://sso.nifty.com/pub/" + $resp.Forms[0].Action
$body = $resp.Forms[0].Fields
$body.item("username") = $cr.username
$body.item("password") = $cr.GetNetworkCredential().password
$body.item("input_selector") = "0"
$body.item("remember") = "1"
$body.Remove("saveLogin")
write-host "** login -> cocolog management top page"
$resp = $null
$resp = Invoke-WebRequest $link -WebSession $session -Body $body -Method "POST"
if($resp.StatusCode -ne 200) { exit; }
# cocolog management top pageでなかったらログイン失敗→UID/PWD入力しなおし
} while($resp.ParsedHtml.title -ne "ココログ管理ページ:@nifty")
# 記事一覧のリンク取得
$blogTopLink = "http://app.f.cocolog-nifty.com" + ($resp.Links | ?{$_.innerText -ne $null -and $_.outerHTML.indexof("<a class=`"blog-menu__item -list box-sub-01`"") -ge 0 }).href
# 記事一覧ページに移動
write-host "** contents list:" $blogTopLink
$currentPageLink = $blogTopLink
$resp = $null
$resp = Invoke-WebRequest $currentPageLink -WebSession $session
if($resp.StatusCode -ne 200) { exit; }
#全ページを舐める
$nextPage = ""
do {
if($resp.Links.count -eq 0) {
exit;
}
# 記事一覧を取得
$resp.Links | ? { $_.outerHTML.indexof("title") -ge 0 } | %{
$title = $_.title
$href = $_.href
"title:`"{0}`"`thref:`"{1}`"" -F $title, $href
$contentLink = "http://app.f.cocolog-nifty.com" + $href
write-host "** contents page:" $contentLink
# 各記事に遷移
$respContent = $null
$respContent = Invoke-WebRequest $contentLink -WebSession $session
if($respContent.StatusCode -ne 200) { exit; }
# 記事の情報を取得→JSONファイル出力
# ファイル名:<エントリ番号>_<記事title>.json
$entryNo = $href.Substring($href.lastIndexOf("/")+1)
$fileName = ("{0}_{1}.json" -F $entryNo, $title)
# ファイル名使用禁止文字をアンダーバーに置き換える
$fileName = $fileName -replace "[`"<>\|:\*\?\\/`r`n\[\]]", "_"
# 内容の改行文字を\nに置き換える(JSONでは"\\n"になる)
$content = @{}
# 記事のtitle,text,text_moreを取得
$text = $respContent.Content
"${entryNo}__entry_title", "${entryNo}__entry_text", "${entryNo}__entry_text_more" | %{
$value = ""
$rgx = [regex]::matches($text, "(?s:<textarea.*?( (id|name)=""${_}"")+.*?>(.*?)</textarea>)")
if($rgx.Success) {
$value = $rgx.Groups[3].value.replace("`n", "\n")
}
$content[$_] = $value
}
# カテゴリ(選択されているもの)
$elmName = "${entryNo}__category_ids"
$categories = @()
$rgxRslt = [regex]::Matches($text, "(?s:<select.*?name=""${elmName}"".*?>(.+?)</select>)")
if($rgxRslt.Success) {
$options = $rgxRslt.Groups[1]
$options -split "</option>" | %{
$rgxOpt = [regex]::Matches($_, "<option.*selected=""selected"".*>.+")
if($rgxOpt.Success) {
$rgxOpt = [regex]::Matches($_, "<option.*value=""(\d+)"".*>(.+)")
if($rgxOpt.Success) {
$category = @{}
for($i=0; $i -lt $rgxOpt.Groups.count/3; $i++) {
$category["id"] = $rgxOpt.Groups[$i*3+1].value
$category["text"] = $rgxOpt.Groups[$i*3+2].value
$categories += $category
}
}
}
}
}
$content[$elmName] = $categories
# ファイル出力
$content | ConvertTo-Json -Compress
$content | ConvertTo-Json -Compress | Out-File $fileName -Encoding UTF8
# 記事一覧に戻る
#write-host "** return to contents list page:" $currentPageLink
#$respContent = $null
#$respContent = Invoke-WebRequest $currentPageLink -WebSession $session
#if($respContent.StatusCode -ne 200) { exit; }
}
# ここでは記事一覧ページにいる
# 次ページの取得
$nextPage = ($resp.Links | ? {$_.class -eq "next" } | %{$_.href})
$nextPageLink = $blogTopLink + $nextPage
if($nextPage.length -gt 0) {
$currentPageLink = $nextPageLink
# 次ページ移動
write-host "** next contents list page:" $currentPageLink
$resp = $null
$resp = Invoke-WebRequest $currentPageLink -WebSession $session
if($resp.StatusCode -ne 200) { exit; }
}
} while($nextPage.length -gt 0)
write-host "** finish!"

2018年7月 1日 (日)

電子証明書について その2

PKCS12ファイルの中に入れてある公開鍵証明書の情報は、X.509という規格に従っている。

RFC5280「Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile」で公開されている。(IPAにある日本語版は、データ型の所とか削ってあるので、併用して英語版を見ると良い)
X.509 は、以下のようになっている。
  • ASN.1という規格で記述されている。
  • TLV形式(タグ・長さ・データ)という形
  • タグは、1バイト。先頭2bitはclass、次の1bitはprimitive/constructedフラグ(p/c)、残り5bitはtag。
    ・class=00BはASN.1で定義されているデータ型。
    class=10Bは文脈依存。例えば、versionの所で使われている。1バイト目0xA0は、X.509v3証明書で示されている"version [0] Version DEFAULT v1."のところ、”class=80 p/c=20 tagid=00”がそれ。tag=0x00なのは"[0]"を示している。他には、"extensions [3]"のところ。0xA3→”class=80 p/c=20 tagid=03”となっている。
    ・primitive/constructedは、1のとき後者で構造体となっていると思えばOK。
    ・tagは、class=0x00、p/c=0x00ならASN.1で決められたデータ型になる。
  • 長さは、1バイト目が0x80より小の場合、データ長0~127バイトを示す。
    0x80より大の場合、7bitでそのあとのバイト数がデータ長を示す。例えば0x82,0x01,0x02としたら0x01*0x100+0x02=データ長258バイトとなる。0x80のときはあまりないと思われるけど、末尾0x00までがデータとなる。
  • データは、長さで示されたバイト数。
    特別なデータ型として、T=0x30や0x31のとき、Vの中が次の構造体のデータを示す。

class=00 p/c=20 tagid=10 len=1142 i=4
  class=00 p/c=20 tagid=10 len=862 i=8
    class=80 p/c=20 tagid=00 len=3 i=10
      class=00 p/c=00 tagid=02 len=1 i=13        *version=3 (値+1で扱う)
      2
    class=00 p/c=00 tagid=02 len=9 i=24        *serialNumber=0x99674fbc78d5f74b
    1.10538914813039E+19
    class=00 p/c=20 tagid=10 len=13 i=26
      class=00 p/c=00 tagid=06 len=9 i=37      *AlgrithmIdentifer OIDはsha256WithRSAEncryption
      1.2.840.113549.1.1.11
      class=00 p/c=00 tagid=05 len=0 i=39
    class=00 p/c=20 tagid=10 len=207 i=42      *発行者(Issuer)
      class=00 p/c=20 tagid=11 len=11 i=44
        class=00 p/c=20 tagid=10 len=9 i=46
          class=00 p/c=00 tagid=06 len=3 i=51  *countryName=JP
          2.5.4.6
          class=00 p/c=00 tagid=13 len=2 i=55
          4a 50
      class=00 p/c=20 tagid=11 len=16 i=57
        class=00 p/c=20 tagid=10 len=14 i=59
          class=00 p/c=00 tagid=06 len=3 i=64  *stateOrProvinceName(ST)=TOKYO
          2.5.4.8
          class=00 p/c=00 tagid=0c len=7 i=73
          53 41 49 54 41 4d 41
      class=00 p/c=20 tagid=11 len=17 i=75
        class=00 p/c=20 tagid=10 len=15 i=77
          class=00 p/c=00 tagid=06 len=3 i=82  *localityName(L)=MINATOKU
          2.5.4.7
          class=00 p/c=00 tagid=0c len=8 i=92
          4b 4f 53 49 47 41 59 41
      class=00 p/c=20 tagid=11 len=16 i=94
        class=00 p/c=20 tagid=10 len=14 i=96
          class=00 p/c=00 tagid=06 len=3 i=101  *organizationName(O)=COMPANY
          2.5.4.10
          class=00 p/c=00 tagid=0c len=7 i=110
          43 4f 4d 50 41 4e 59
      class=00 p/c=20 tagid=11 len=17 i=112
        class=00 p/c=20 tagid=10 len=15 i=114    *organizationalUnitName(OU)=JIGYOUBU
          class=00 p/c=00 tagid=06 len=3 i=119
          2.5.4.11
          class=00 p/c=00 tagid=0c len=8 i=129
          4a 49 47 59 4f 55 42 55
      class=00 p/c=20 tagid=11 len=11 i=131
        class=00 p/c=20 tagid=10 len=9 i=133
          class=00 p/c=00 tagid=06 len=3 i=138  *commonName(CN)=BU
          2.5.4.3
          class=00 p/c=00 tagid=0c len=2 i=142
          42 55
      class=00 p/c=20 tagid=11 len=15 i=144
        class=00 p/c=20 tagid=10 len=13 i=146
          class=00 p/c=00 tagid=06 len=3 i=151  *title=title1
          2.5.4.12
          class=00 p/c=00 tagid=0c len=6 i=159
          74 69 74 6c 65 31
      class=00 p/c=20 tagid=11 len=17 i=161
        class=00 p/c=20 tagid=10 len=15 i=163
          class=00 p/c=00 tagid=06 len=3 i=168  *surname(SN)=surname1
          2.5.4.4
          class=00 p/c=00 tagid=0c len=8 i=178
          73 75 72 6e 61 6d 65 31
      class=00 p/c=20 tagid=11 len=19 i=180
        class=00 p/c=20 tagid=10 len=17 i=182
          class=00 p/c=00 tagid=06 len=3 i=187  *givenName(GN)=givenname1
          2.5.4.42
          class=00 p/c=00 tagid=0c len=10 i=199
          67 69 76 65 6e 6e 61 6d 65 31
      class=00 p/c=20 tagid=11 len=17 i=201
        class=00 p/c=20 tagid=10 len=15 i=203
          class=00 p/c=00 tagid=06 len=3 i=208  *initials=initial1
          2.5.4.43
          class=00 p/c=00 tagid=0c len=8 i=218
          69 6e 69 74 69 61 6c 31
      class=00 p/c=20 tagid=11 len=29 i=220
        class=00 p/c=20 tagid=10 len=27 i=222
          class=00 p/c=00 tagid=06 len=9 i=233  *emailAddress=test1@test.com
          1.2.840.113549.1.9.1
          class=00 p/c=00 tagid=16 len=14 i=249
          74 65 73 74 31 40 74 65 73 74 2e 63 6f 6d
    class=00 p/c=20 tagid=10 len=30 i=251      *vallidity
      class=00 p/c=00 tagid=17 len=13 i=266    *notBefore=180701064133Z UTCTime->2018/07/01 06:41:33
      31 38 30 37 30 31 30 36 34 31 33 33 5a
      class=00 p/c=00 tagid=17 len=13 i=281    *notAfter =280628064133Z UTCTime->2028/06/28 06:41:33
      32 38 30 36 32 38 30 36 34 31 33 33 5a
    class=00 p/c=20 tagid=10 len=207 i=284
      class=00 p/c=20 tagid=11 len=11 i=286      *Issuer (内容はSubjectと同じ)
        class=00 p/c=20 tagid=10 len=9 i=288
          class=00 p/c=00 tagid=06 len=3 i=293
          2.5.4.6
          class=00 p/c=00 tagid=13 len=2 i=297
          4a 50
      class=00 p/c=20 tagid=11 len=16 i=299
        class=00 p/c=20 tagid=10 len=14 i=301
          class=00 p/c=00 tagid=06 len=3 i=306
          2.5.4.8
          class=00 p/c=00 tagid=0c len=7 i=315
          53 41 49 54 41 4d 41
      class=00 p/c=20 tagid=11 len=17 i=317
        class=00 p/c=20 tagid=10 len=15 i=319
          class=00 p/c=00 tagid=06 len=3 i=324
          2.5.4.7
          class=00 p/c=00 tagid=0c len=8 i=334
          4b 4f 53 49 47 41 59 41
      class=00 p/c=20 tagid=11 len=16 i=336
        class=00 p/c=20 tagid=10 len=14 i=338
          class=00 p/c=00 tagid=06 len=3 i=343
          2.5.4.10
          class=00 p/c=00 tagid=0c len=7 i=352
          43 4f 4d 50 41 4e 59
      class=00 p/c=20 tagid=11 len=17 i=354
        class=00 p/c=20 tagid=10 len=15 i=356
          class=00 p/c=00 tagid=06 len=3 i=361
          2.5.4.11
          class=00 p/c=00 tagid=0c len=8 i=371
          4a 49 47 59 4f 55 42 55
      class=00 p/c=20 tagid=11 len=11 i=373
        class=00 p/c=20 tagid=10 len=9 i=375
          class=00 p/c=00 tagid=06 len=3 i=380
          2.5.4.3
          class=00 p/c=00 tagid=0c len=2 i=384
          42 55
      class=00 p/c=20 tagid=11 len=15 i=386
        class=00 p/c=20 tagid=10 len=13 i=388
          class=00 p/c=00 tagid=06 len=3 i=393
          2.5.4.12
          class=00 p/c=00 tagid=0c len=6 i=401
          74 69 74 6c 65 31
      class=00 p/c=20 tagid=11 len=17 i=403
        class=00 p/c=20 tagid=10 len=15 i=405
          class=00 p/c=00 tagid=06 len=3 i=410
          2.5.4.4
          class=00 p/c=00 tagid=0c len=8 i=420
          73 75 72 6e 61 6d 65 31
      class=00 p/c=20 tagid=11 len=19 i=422
        class=00 p/c=20 tagid=10 len=17 i=424
          class=00 p/c=00 tagid=06 len=3 i=429
          2.5.4.42
          class=00 p/c=00 tagid=0c len=10 i=441
          67 69 76 65 6e 6e 61 6d 65 31
      class=00 p/c=20 tagid=11 len=17 i=443
        class=00 p/c=20 tagid=10 len=15 i=445
          class=00 p/c=00 tagid=06 len=3 i=450
          2.5.4.43
          class=00 p/c=00 tagid=0c len=8 i=460
          69 6e 69 74 69 61 6c 31
      class=00 p/c=20 tagid=11 len=29 i=462
        class=00 p/c=20 tagid=10 len=27 i=464
          class=00 p/c=00 tagid=06 len=9 i=475
          1.2.840.113549.1.9.1
          class=00 p/c=00 tagid=16 len=14 i=491
          74 65 73 74 31 40 74 65 73 74 2e 63 6f 6d
  class=00 p/c=20 tagid=10 len=290 i=495          *SubjectPublicKeyInfo
    class=00 p/c=20 tagid=10 len=13 i=497
      class=00 p/c=00 tagid=06 len=9 i=508      *algorithm=RSA encryption
      1.2.840.113549.1.1.1
      class=00 p/c=00 tagid=05 len=0 i=510
    class=00 p/c=00 tagid=03 len=271 i=785        *subjecPublicKey
    00 30 82 01 0a 02 82 01 01 00 da 7e c9 0b f6 60 ff c0 42 b1 7c 2a 59 0f 5a 89 4a f7 50 52 20 35 c4 20 8a e9 c0 b5 22 d9 e0 f0 e3 a0 01 bc 6e 74 a0 88 b1 55 b3 b5 a5 e9 94 21 28 dc 20 fe 1f 8f 66 a4 25 10 83 a5 4e 53 25 2c 80 b4 d2 7f 01 b7 fa 17 ec 83 84 d3 84 5e 05 81 ac fa a9 c7 27 19 72 ec ba 66 7e 0b 33 63 e3 b0 c8 77 88 b9 21 e3 48 6c df 89 55 1d 7f 9b e9 73 4f da 78 0c d1 25 88 d3 18 24 57 9c 73 0e 22 e6 da 53 f9 33 42 bc 9c e4 59 80 81 3c 7f 27 3f d7 5b 52 95 db 94 5d b7 33 b4 56 d6 ea 53 bd 74 82 92 51 dc bb 68 64 74 8c 52 91 75 39 a2 5f dd 77 0b c5 79 59 28 09 5f 87 eb d6 0c bc fe 16 e7 55 b4 38 a6 45 f5 9f aa 06 95 6c 90 e3 16 38 96 b6 ad 0e bf 55 39 1b 65 12 78 91 15 fb 90 93 a8 26 74 67 4a 77 f2 fe e5 37 d1 4c a1 8d a7 6d 98 56 9e 9b c8 74 7f 62 fb a2 f6 1d ff 97 ca 58 69 91 02 03 01 00 01
    class=80 p/c=20 tagid=03 len=83 i=870        *Extensions
    30 51 30 1d 06 03 55 1d 0e 04 16 04 14 fd 36 ca 12 16 ec c9 62 b9 15 33 d3 a3 a8 11 10 2b 43 5c 16 30 1f 06 03 55 1d 23 04 18 30 16 80 14 fd 36 ca 12 16 ec c9 62 b9 15 33 d3 a3 a8 11 10 2b 43 5c 16 30 0f 06 03 55 1d 13 01 01 ff 04 05 30 03 01 01 ff
    class=00 p/c=20 tagid=10 len=13 i=872
      class=00 p/c=00 tagid=06 len=9 i=883      *signatureAlgrithm=sha256WithRSAEncryption
      1.2.840.113549.1.1.11
      class=00 p/c=00 tagid=05 len=0 i=885
  class=00 p/c=00 tagid=03 len=257 i=1146          *signature
  00 22 87 e4 5e 43 31 4f 4b ea 51 ee dc d5 a9 0d c3 85 df d5 b9 80 f5 6f a1 b4 0a e7 8e 8c c5 0c 2d be ad c7 50 ab df 38 1e ae 73 7a 33 b9 48 02 d8 9d 98 57 a7 ed 09 15 ff 22 fe 4c ee a0 54 6e 34 b6 2f ca 1c 19 03 97 8f 67 72 3a 81 ae 8a dd fe 67 2e b8 2e 48 04 ad ce a6 a0 69 3a e7 67 b1 79 4a cd 33 91 1e 98 30 56 f0 14 4c 5a dd 97 b8 7a 98 7a dc 31 60 fd e6 bd a0 6b 5e 6f 9e 5b b9 3f b9 81 f1 89 15 b5 60 e4 40 40 f7 10 90 d9 46 68 44 3b ac 6d 55 0b 52 50 01 d5 71 0b 3e 9e 3c 35 06 f5 e1 f0 12 97 c5 41 45 9c 5b 7c a0 9f e4 64 36 8d 25 c5 11 7a d3 f7 8b ee 6b 00 c5 3f dd 60 78 ae 20 d6 48 44 44 a5 35 cc d9 73 d1 ee c7 80 f3 7b 91 49 f8 65 a5 ab 93 a9 fc ec b1 cf eb fb 5f 88 47 e3 64 c6 e4 69 c4 f2 96 67 bb 28 ec 28 e2 ad f5 89 3a 3b 31 63 95 d5 5e df 4b 2d c9 95

●Extensionsの部分を切り出して、構造を見てみる。

class=00 p/c=20 tagid=10 len=81 i=2
  class=00 p/c=20 tagid=10 len=29 i=4
    class=00 p/c=00 tagid=06 len=3 i=9        *Subject Key Identifier
    2.5.29.14
    class=00 p/c=00 tagid=04 len=22 i=33
    04 14 fd 36 ca 12 16 ec c9 62 b9 15 33 d3 a3 a8 11 10 2b 43 5c 16
  class=00 p/c=20 tagid=10 len=31 i=35
    class=00 p/c=00 tagid=06 len=3 i=40        *Authority Key Identifier
    2.5.29.35
    class=00 p/c=00 tagid=04 len=24 i=66
    30 16 80 14 fd 36 ca 12 16 ec c9 62 b9 15 33 d3 a3 a8 11 10 2b 43 5c 16
  class=00 p/c=20 tagid=10 len=15 i=68
    class=00 p/c=00 tagid=06 len=3 i=73        *Basic Constraints
    2.5.29.19
    class=00 p/c=00 tagid=01 len=1 i=76
    ff
class=00 p/c=00 tagid=04 len=5 i=83
30 03 01 01 ff

●Extensionsを切り出して関数に食わせた手順。dispASN1は前もって定義している

PS D:\cert> $r=New-Object regex("[0-9a-fA-F]{2}"); $tmp=@();
PS D:\cert> "30 51 30 1d 06 03 55 1d 0e 04 16 04 14 fd 36 ca 12 16 ec c9 62 b9 15 33 d3 a3 a8 11 10 2b 43 5c 16 30 1f 06
 03 55 1d 23 04 18 30 16 80 14 fd 36 ca 12 16 ec c9 62 b9 15 33 d3 a3 a8 11 10 2b 43 5c 16 30 0f 06 03 55 1d 13 01 01 ff
 04 05 30 03 01 01 ff" | %{$r.Matches($_)} | %{$tmp += [Convert]::ToByte("0x" + $_.Value, 16)}
PS D:\cert> dispASN1 $tmp
dispASN1 start
class=00 p/c=20 tagid=10 len=81 i=2
class=00 p/c=20 tagid=10 len=29 i=4
class=00 p/c=00 tagid=06 len=3 i=9
2.5.29.14
class=00 p/c=00 tagid=04 len=22 i=33
04 14 fd 36 ca 12 16 ec c9 62 b9 15 33 d3 a3 a8 11 10 2b 43 5c 16
class=00 p/c=20 tagid=10 len=31 i=35
class=00 p/c=00 tagid=06 len=3 i=40
2.5.29.35
class=00 p/c=00 tagid=04 len=24 i=66
30 16 80 14 fd 36 ca 12 16 ec c9 62 b9 15 33 d3 a3 a8 11 10 2b 43 5c 16
class=00 p/c=20 tagid=10 len=15 i=68
class=00 p/c=00 tagid=06 len=3 i=73
2.5.29.19
class=00 p/c=00 tagid=01 len=1 i=76
ff
class=00 p/c=00 tagid=04 len=5 i=83
30 03 01 01 ff
dispASN1 end

電子証明書について

お仕事で、電子証明書ファイルの情報について調べてみた。

●opensslのコマンドでPKCS12ファイルを作ってみて、中身を見る

openssl req -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/C=JP/ST=SAITAMA/L=KOSIGAYA/O=COMPANY/OU=JIGYOUBU/CN=BU/title=title1/SN=surname1/GN=givenname1/initials=initial1/emailAddress=test1@test.com" -config ./openssl.cfg -keyout test.pem -out test.crt

openssl pkcs12 -export -in test.crt -inkey test.pem -out test.p12

openssl x509 -text -in test.crt

●opensslのコマンドでPKCS12ファイルまで作ってみる。

D:\cert>openssl req -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/C=JP/ST=SAITAMA/L=KOSIGAYA/O=COMPANY/OU=JIGYOUBU/CN=BU/title=title1/SN=surname1/GN=givenname1/initials=initial1/emailAddress=test1@test.com" -config ./openssl.cfg -keyout test.pem -out test.crt
Generating a 2048 bit RSA private key
........................+++
....................+++
writing new private key to 'test.pem'
-----

D:\cert>openssl pkcs12 -export -in test.crt -inkey test.pem -out test.p12
Enter Export Password:
Verifying - Enter Export Password:

D:\cert>dir
 ドライブ D のボリューム ラベルがありません。
 ボリューム シリアル番号は 86F4-1821 です

 D:\cert のディレクトリ

2018/07/01  14:56    

          . 2018/07/01  14:56   

          .. 2018/07/01  14:56             1,024 .rnd 2018/07/01  14:37            11,198 openssl.cfg 2018/07/01  14:56             1,604 test.crt 2018/07/01  14:56             2,725 test.p12 2018/07/01  14:56             1,732 test.pem                5 個のファイル              18,283 バイト                2 個のディレクトリ  124,596,654,080 バイトの空き領域


●opensslコマンドでcrtファイルの内容を見てみる。

D:\cert>openssl x509 -text -in test.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            99:67:4f:bc:78:d5:f7:4b
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = JP, ST = SAITAMA, L = KOSIGAYA, O = COMPANY, OU = JIGYOUBU,CN = BU, title = title1, SN = surname1, GN = givenname1, initials = initial1, emailAddress = test1@test.com
        Validity
            Not Before: Jul  1 06:41:33 2018 GMT
            Not After : Jun 28 06:41:33 2028 GMT
        Subject: C = JP, ST = SAITAMA, L = KOSIGAYA, O = COMPANY, OU = JIGYOUBU, CN = BU, title = title1, SN = surname1, GN = givenname1, initials = initial1, emailAddress = test1@test.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:da:7e:c9:0b:f6:60:ff:c0:42:b1:7c:2a:59:0f:
                    5a:89:4a:f7:50:52:20:35:c4:20:8a:e9:c0:b5:22:
                    d9:e0:f0:e3:a0:01:bc:6e:74:a0:88:b1:55:b3:b5:
                    a5:e9:94:21:28:dc:20:fe:1f:8f:66:a4:25:10:83:
                    a5:4e:53:25:2c:80:b4:d2:7f:01:b7:fa:17:ec:83:
                    84:d3:84:5e:05:81:ac:fa:a9:c7:27:19:72:ec:ba:
                    66:7e:0b:33:63:e3:b0:c8:77:88:b9:21:e3:48:6c:
                    df:89:55:1d:7f:9b:e9:73:4f:da:78:0c:d1:25:88:
                    d3:18:24:57:9c:73:0e:22:e6:da:53:f9:33:42:bc:
                    9c:e4:59:80:81:3c:7f:27:3f:d7:5b:52:95:db:94:
                    5d:b7:33:b4:56:d6:ea:53:bd:74:82:92:51:dc:bb:
                    68:64:74:8c:52:91:75:39:a2:5f:dd:77:0b:c5:79:
                    59:28:09:5f:87:eb:d6:0c:bc:fe:16:e7:55:b4:38:
                    a6:45:f5:9f:aa:06:95:6c:90:e3:16:38:96:b6:ad:
                    0e:bf:55:39:1b:65:12:78:91:15:fb:90:93:a8:26:
                    74:67:4a:77:f2:fe:e5:37:d1:4c:a1:8d:a7:6d:98:
                    56:9e:9b:c8:74:7f:62:fb:a2:f6:1d:ff:97:ca:58:
                    69:91
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                FD:36:CA:12:16:EC:C9:62:B9:15:33:D3:A3:A8:11:10:2B:43:5C:16
            X509v3 Authority Key Identifier:
                keyid:FD:36:CA:12:16:EC:C9:62:B9:15:33:D3:A3:A8:11:10:2B:43:5C:16

            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: sha256WithRSAEncryption
         22:87:e4:5e:43:31:4f:4b:ea:51:ee:dc:d5:a9:0d:c3:85:df:
         d5:b9:80:f5:6f:a1:b4:0a:e7:8e:8c:c5:0c:2d:be:ad:c7:50:
         ab:df:38:1e:ae:73:7a:33:b9:48:02:d8:9d:98:57:a7:ed:09:
         15:ff:22:fe:4c:ee:a0:54:6e:34:b6:2f:ca:1c:19:03:97:8f:
         67:72:3a:81:ae:8a:dd:fe:67:2e:b8:2e:48:04:ad:ce:a6:a0:
         69:3a:e7:67:b1:79:4a:cd:33:91:1e:98:30:56:f0:14:4c:5a:
         dd:97:b8:7a:98:7a:dc:31:60:fd:e6:bd:a0:6b:5e:6f:9e:5b:
         b9:3f:b9:81:f1:89:15:b5:60:e4:40:40:f7:10:90:d9:46:68:
         44:3b:ac:6d:55:0b:52:50:01:d5:71:0b:3e:9e:3c:35:06:f5:
         e1:f0:12:97:c5:41:45:9c:5b:7c:a0:9f:e4:64:36:8d:25:c5:
         11:7a:d3:f7:8b:ee:6b:00:c5:3f:dd:60:78:ae:20:d6:48:44:
         44:a5:35:cc:d9:73:d1:ee:c7:80:f3:7b:91:49:f8:65:a5:ab:
         93:a9:fc:ec:b1:cf:eb:fb:5f:88:47:e3:64:c6:e4:69:c4:f2:
         96:67:bb:28:ec:28:e2:ad:f5:89:3a:3b:31:63:95:d5:5e:df:
         4b:2d:c9:95
-----BEGIN CERTIFICATE-----
MIIEdjCCA16gAwIBAgIJAJlnT7x41fdLMA0GCSqGSIb3DQEBCwUAMIHPMQswCQYD
VQQGEwJKUDEQMA4GA1UECAwHU0FJVEFNQTERMA8GA1UEBwwIS09TSUdBWUExEDAO
BgNVBAoMB0NPTVBBTlkxETAPBgNVBAsMCEpJR1lPVUJVMQswCQYDVQQDDAJCVTEP
MA0GA1UEDAwGdGl0bGUxMREwDwYDVQQEDAhzdXJuYW1lMTETMBEGA1UEKgwKZ2l2
ZW5uYW1lMTERMA8GA1UEKwwIaW5pdGlhbDExHTAbBgkqhkiG9w0BCQEWDnRlc3Qx
QHRlc3QuY29tMB4XDTE4MDcwMTA2NDEzM1oXDTI4MDYyODA2NDEzM1owgc8xCzAJ
BgNVBAYTAkpQMRAwDgYDVQQIDAdTQUlUQU1BMREwDwYDVQQHDAhLT1NJR0FZQTEQ
MA4GA1UECgwHQ09NUEFOWTERMA8GA1UECwwISklHWU9VQlUxCzAJBgNVBAMMAkJV
MQ8wDQYDVQQMDAZ0aXRsZTExETAPBgNVBAQMCHN1cm5hbWUxMRMwEQYDVQQqDApn
aXZlbm5hbWUxMREwDwYDVQQrDAhpbml0aWFsMTEdMBsGCSqGSIb3DQEJARYOdGVz
dDFAdGVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDafskL
9mD/wEKxfCpZD1qJSvdQUiA1xCCK6cC1Itng8OOgAbxudKCIsVWztaXplCEo3CD+
H49mpCUQg6VOUyUsgLTSfwG3+hfsg4TThF4Fgaz6qccnGXLsumZ+CzNj47DId4i5
IeNIbN+JVR1/m+lzT9p4DNEliNMYJFeccw4i5tpT+TNCvJzkWYCBPH8nP9dbUpXb
lF23M7RW1upTvXSCklHcu2hkdIxSkXU5ol/ddwvFeVkoCV+H69YMvP4W51W0OKZF
9Z+qBpVskOMWOJa2rQ6/VTkbZRJ4kRX7kJOoJnRnSnfy/uU30UyhjadtmFaem8h0
f2L7ovYd/5fKWGmRAgMBAAGjUzBRMB0GA1UdDgQWBBT9NsoSFuzJYrkVM9OjqBEQ
K0NcFjAfBgNVHSMEGDAWgBT9NsoSFuzJYrkVM9OjqBEQK0NcFjAPBgNVHRMBAf8E
BTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAih+ReQzFPS+pR7tzVqQ3Dhd/VuYD1
b6G0CueOjMUMLb6tx1Cr3zgernN6M7lIAtidmFen7QkV/yL+TO6gVG40ti/KHBkD
l49ncjqBrord/mcuuC5IBK3OpqBpOudnsXlKzTORHpgwVvAUTFrdl7h6mHrcMWD9
5r2ga15vnlu5P7mB8YkVtWDkQED3EJDZRmhEO6xtVQtSUAHVcQs+njw1BvXh8BKX
xUFFnFt8oJ/kZDaNJcURetP3i+5rAMU/3WB4riDWSEREpTXM2XPR7seA83uRSfhl
pauTqfzssc/r+1+IR+NkxuRpxPKWZ7so7CjirfWJOjsxY5XVXt9LLcmV
-----END CERTIFICATE-----

●Powershellで公開鍵証明書の情報をASN.1として取得してみる

function dispASN1($x509bytes) {
write-host "dispASN1 start"
	$enc = [system.Text.Encoding]::GetEncoding("UTF-8")
	$i=0
	while($i -lt $x509bytes.length) {

		# get class & tagid(p/c)
		$class=($x509bytes[$i] -band 0xC0)
		$pc=($x509bytes[$i] -band 0x20)
		$tagid=($x509bytes[$i] -band 0x1f)
		$i++

		# get length
		$len=0
		if(($x509bytes[$i] -band 0x80) -eq 0x80) {
			$cnt=$x509bytes[$i] -band 0x7f
			$i++
			for($j=0; $j -lt $cnt; $j++) {
				$len=$len*0x100+$x509bytes[$i]
				$i++
			}
		} else {
			$len=$x509bytes[$i]
			$i++
		}

		$d=@()
		#if(($pc -eq 0) -and (($tagid -ne 0x00) -and ($tagid -ne 0x10) -and ($tagid -ne 0x11))) {
		if((($tagid -ne 0x00) -and ($tagid -ne 0x10) -and ($tagid -ne 0x11))) {
			for($j=0;$j -lt $len;$j++){
				$d += $x509bytes[$i]
				$i++
			}
		}
		write-host("class={0:x2} p/c={1:x2} tagid={2:x2} len={3} i={4}" -F $class, $pc, $tagid, $len, $i)
		if($class -eq 0) {
			switch($tagid) {
				{$_ -eq 0x02} {	# INTEGER
					$d1=0
					for($j=0;$j -lt $len; $j++) {
						$d1=$d1*0x100+$d[$j]
					}
					write-host("{0}" -F $d1)
				}
				#{($_ -eq 0x04) -and ($pc -ne 0)} {	# OCTET STRING
				{$_ -eq 0x04} {	# OCTET STRING
					if ($pc -eq 0) {
						foreach($d1 in $d) { write-host -nonewline ("{0:x2} " -F $d1)}
						if($d.count -gt 0) {write-host}
					} else {
						dipASN1 $d
					}
					break
				}
				{$_ -eq 0x06} {	# OID
					write-host -nonewline ("{0}.{1}" -F ([math]::Floor($d[0]/40)), ($d[0]%40))
					$id=0
					for($j=1;$j -lt $len; $j++) {
						$id = $id*128+($d[$j] -band 0x7f)
						if(($d[$j] -band 0x80) -ne 0x80) {
							write-host -nonewline (".{0}" -F $id)
							$id=0
						}
					}
					write-host
					break
				}
				{($_ -eq 0x10) -or ($_ -eq 0x11)} {
					break
				}
				default {
					foreach($d1 in $d) { write-host -nonewline ("{0:x2} " -F $d1)}
					if($d.count -gt 0) {write-host}
				}
			}
		} else {
			foreach($d1 in $d) { write-host -nonewline ("{0:x2} " -F $d1)}
			write-host
		}
	}
write-host "dispASN1 end"
}


if ($args.count -ne 1) {
	write-host "Invalid Argment. Perase set P12 File"
	return
}

$x509data = Get-PfxCertificate $args[0]
$certData = $x509data.GetRawCertData()

#$file="D:\work\暗号\my-identity.p12"
#$certData=@();[System.IO.File]::ReadAllBytes($file) | %{"{0:x2}" -F $_ }| %{$certData += [Convert]::ToByte("0x" + $_, 16)}
dispASN1 $certData

●その結果

PS D:\cert> .\dispASN1.ps1 .\test.p12
パスワードの入力: ****

dispASN1 start
class=00 p/c=20 tagid=10 len=1142 i=4
class=00 p/c=20 tagid=10 len=862 i=8
class=80 p/c=20 tagid=00 len=3 i=10

class=00 p/c=00 tagid=02 len=1 i=13
2
class=00 p/c=00 tagid=02 len=9 i=24
1.10538914813039E+19
class=00 p/c=20 tagid=10 len=13 i=26
class=00 p/c=00 tagid=06 len=9 i=37
1.2.840.113549.1.1.11
class=00 p/c=00 tagid=05 len=0 i=39
class=00 p/c=20 tagid=10 len=207 i=42
class=00 p/c=20 tagid=11 len=11 i=44
class=00 p/c=20 tagid=10 len=9 i=46
class=00 p/c=00 tagid=06 len=3 i=51
2.5.4.6
class=00 p/c=00 tagid=13 len=2 i=55
4a 50
class=00 p/c=20 tagid=11 len=16 i=57
class=00 p/c=20 tagid=10 len=14 i=59
class=00 p/c=00 tagid=06 len=3 i=64
2.5.4.8
class=00 p/c=00 tagid=0c len=7 i=73
53 41 49 54 41 4d 41
class=00 p/c=20 tagid=11 len=17 i=75
class=00 p/c=20 tagid=10 len=15 i=77
class=00 p/c=00 tagid=06 len=3 i=82
2.5.4.7
class=00 p/c=00 tagid=0c len=8 i=92
4b 4f 53 49 47 41 59 41
class=00 p/c=20 tagid=11 len=16 i=94
class=00 p/c=20 tagid=10 len=14 i=96
class=00 p/c=00 tagid=06 len=3 i=101
2.5.4.10
class=00 p/c=00 tagid=0c len=7 i=110
43 4f 4d 50 41 4e 59
class=00 p/c=20 tagid=11 len=17 i=112
class=00 p/c=20 tagid=10 len=15 i=114
class=00 p/c=00 tagid=06 len=3 i=119
2.5.4.11
class=00 p/c=00 tagid=0c len=8 i=129
4a 49 47 59 4f 55 42 55
class=00 p/c=20 tagid=11 len=11 i=131
class=00 p/c=20 tagid=10 len=9 i=133
class=00 p/c=00 tagid=06 len=3 i=138
2.5.4.3
class=00 p/c=00 tagid=0c len=2 i=142
42 55
class=00 p/c=20 tagid=11 len=15 i=144
class=00 p/c=20 tagid=10 len=13 i=146
class=00 p/c=00 tagid=06 len=3 i=151
2.5.4.12
class=00 p/c=00 tagid=0c len=6 i=159
74 69 74 6c 65 31
class=00 p/c=20 tagid=11 len=17 i=161
class=00 p/c=20 tagid=10 len=15 i=163
class=00 p/c=00 tagid=06 len=3 i=168
2.5.4.4
class=00 p/c=00 tagid=0c len=8 i=178
73 75 72 6e 61 6d 65 31
class=00 p/c=20 tagid=11 len=19 i=180
class=00 p/c=20 tagid=10 len=17 i=182
class=00 p/c=00 tagid=06 len=3 i=187
2.5.4.42
class=00 p/c=00 tagid=0c len=10 i=199
67 69 76 65 6e 6e 61 6d 65 31
class=00 p/c=20 tagid=11 len=17 i=201
class=00 p/c=20 tagid=10 len=15 i=203
class=00 p/c=00 tagid=06 len=3 i=208
2.5.4.43
class=00 p/c=00 tagid=0c len=8 i=218
69 6e 69 74 69 61 6c 31
class=00 p/c=20 tagid=11 len=29 i=220
class=00 p/c=20 tagid=10 len=27 i=222
class=00 p/c=00 tagid=06 len=9 i=233
1.2.840.113549.1.9.1
class=00 p/c=00 tagid=16 len=14 i=249
74 65 73 74 31 40 74 65 73 74 2e 63 6f 6d
class=00 p/c=20 tagid=10 len=30 i=251
class=00 p/c=00 tagid=17 len=13 i=266
31 38 30 37 30 31 30 36 34 31 33 33 5a
class=00 p/c=00 tagid=17 len=13 i=281
32 38 30 36 32 38 30 36 34 31 33 33 5a
class=00 p/c=20 tagid=10 len=207 i=284
class=00 p/c=20 tagid=11 len=11 i=286
class=00 p/c=20 tagid=10 len=9 i=288
class=00 p/c=00 tagid=06 len=3 i=293
2.5.4.6
class=00 p/c=00 tagid=13 len=2 i=297
4a 50
class=00 p/c=20 tagid=11 len=16 i=299
class=00 p/c=20 tagid=10 len=14 i=301
class=00 p/c=00 tagid=06 len=3 i=306
2.5.4.8
class=00 p/c=00 tagid=0c len=7 i=315
53 41 49 54 41 4d 41
class=00 p/c=20 tagid=11 len=17 i=317
class=00 p/c=20 tagid=10 len=15 i=319
class=00 p/c=00 tagid=06 len=3 i=324
2.5.4.7
class=00 p/c=00 tagid=0c len=8 i=334
4b 4f 53 49 47 41 59 41
class=00 p/c=20 tagid=11 len=16 i=336
class=00 p/c=20 tagid=10 len=14 i=338
class=00 p/c=00 tagid=06 len=3 i=343
2.5.4.10
class=00 p/c=00 tagid=0c len=7 i=352
43 4f 4d 50 41 4e 59
class=00 p/c=20 tagid=11 len=17 i=354
class=00 p/c=20 tagid=10 len=15 i=356
class=00 p/c=00 tagid=06 len=3 i=361
2.5.4.11
class=00 p/c=00 tagid=0c len=8 i=371
4a 49 47 59 4f 55 42 55
class=00 p/c=20 tagid=11 len=11 i=373
class=00 p/c=20 tagid=10 len=9 i=375
class=00 p/c=00 tagid=06 len=3 i=380
2.5.4.3
class=00 p/c=00 tagid=0c len=2 i=384
42 55
class=00 p/c=20 tagid=11 len=15 i=386
class=00 p/c=20 tagid=10 len=13 i=388
class=00 p/c=00 tagid=06 len=3 i=393
2.5.4.12
class=00 p/c=00 tagid=0c len=6 i=401
74 69 74 6c 65 31
class=00 p/c=20 tagid=11 len=17 i=403
class=00 p/c=20 tagid=10 len=15 i=405
class=00 p/c=00 tagid=06 len=3 i=410
2.5.4.4
class=00 p/c=00 tagid=0c len=8 i=420
73 75 72 6e 61 6d 65 31
class=00 p/c=20 tagid=11 len=19 i=422
class=00 p/c=20 tagid=10 len=17 i=424
class=00 p/c=00 tagid=06 len=3 i=429
2.5.4.42
class=00 p/c=00 tagid=0c len=10 i=441
67 69 76 65 6e 6e 61 6d 65 31
class=00 p/c=20 tagid=11 len=17 i=443
class=00 p/c=20 tagid=10 len=15 i=445
class=00 p/c=00 tagid=06 len=3 i=450
2.5.4.43
class=00 p/c=00 tagid=0c len=8 i=460
69 6e 69 74 69 61 6c 31
class=00 p/c=20 tagid=11 len=29 i=462
class=00 p/c=20 tagid=10 len=27 i=464
class=00 p/c=00 tagid=06 len=9 i=475
1.2.840.113549.1.9.1
class=00 p/c=00 tagid=16 len=14 i=491
74 65 73 74 31 40 74 65 73 74 2e 63 6f 6d
class=00 p/c=20 tagid=10 len=290 i=495
class=00 p/c=20 tagid=10 len=13 i=497
class=00 p/c=00 tagid=06 len=9 i=508
1.2.840.113549.1.1.1
class=00 p/c=00 tagid=05 len=0 i=510
class=00 p/c=00 tagid=03 len=271 i=785
00 30 82 01 0a 02 82 01 01 00 da 7e c9 0b f6 60 ff c0 42 b1 7c 2a 59 0f 5a 89 4a f7 50 52 20 35 c4 20 8a e9 c0 b5 22 d9 e0 f0 e3 a0 01 bc 6e 74 a0 88 b1 55 b3 b5 a5 e9 94 21 28 dc 20 fe 1f 8f 66 a4 25 10 83 a5 4e 53 25 2c 80 b4 d2 7f 01 b7 fa 17 ec 83 84 d3 84 5e 05 81 ac fa a9 c7 27 19 72 ec ba 66 7e 0b 33 63 e3 b0 c8 77 88 b9 21 e3 48 6c df 89 55 1d 7f 9b e9 73 4f da 78 0c d1 25 88 d3 18 24 57 9c 73 0e 22 e6 da 53 f9 33 42 bc 9c e4 59 80 81 3c 7f 27 3f d7 5b 52 95 db 94 5d b7 33 b4 56 d6 ea 53 bd 74 82 92 51 dc bb 68 64 74 8c 52 91 75 39 a2 5f dd 77 0b c5 79 59 28 09 5f 87 eb d6 0c bc fe 16 e7 55 b4 38 a6 45 f5 9f aa 06 95 6c 90 e3 16 38 96 b6 ad 0e bf 55 39 1b 65 12 78 91 15 fb 90 93 a8 26 74 67 4a 77 f2 fe e5 37 d1 4c a1 8d a7 6d 98 56 9e 9b c8 74 7f 62 fb a2 f6 1d ff 97 ca 58 69 91 02 03 01 00 01
class=80 p/c=20 tagid=03 len=83 i=870
30 51 30 1d 06 03 55 1d 0e 04 16 04 14 fd 36 ca 12 16 ec c9 62 b9 15 33 d3 a3 a8 11 10 2b 43 5c 16 30 1f 06 03 55 1d 23 04 18 30 16 80 14 fd 36 ca 12 16 ec c9 62 b9 15 33 d3 a3 a8 11 10 2b 43 5c 16 30 0f 06 03 55 1d 13 01 01 ff 04 05 30 03 01 01 ff
class=00 p/c=20 tagid=10 len=13 i=872
class=00 p/c=00 tagid=06 len=9 i=883
1.2.840.113549.1.1.11
class=00 p/c=00 tagid=05 len=0 i=885
class=00 p/c=00 tagid=03 len=257 i=1146
00 22 87 e4 5e 43 31 4f 4b ea 51 ee dc d5 a9 0d c3 85 df d5 b9 80 f5 6f a1 b4 0a e7 8e 8c c5 0c 2d be ad c7 50 ab df 38 1e ae 73 7a 33 b9 48 02 d8 9d 98 57 a7 ed 09 15 ff 22 fe 4c ee a0 54 6e 34 b6 2f ca 1c 19 03 97 8f 67 72 3a 81 ae 8a dd fe 67 2e b8 2e 48 04 ad ce a6 a0 69 3a e7 67 b1 79 4a cd 33 91 1e 98 30 56 f0 14 4c 5a dd 97 b8 7a 98 7a dc 31 60 fd e6 bd a0 6b 5e 6f 9e 5b b9 3f b9 81 f1 89 15 b5 60 e4 40 40 f7 10 90 d9 46 68 44 3b ac 6d 55 0b 52 50 01 d5 71 0b 3e 9e 3c 35 06 f5 e1 f0 12 97 c5 41 45 9c 5b 7c a0 9f e4 64 36 8d 25 c5 11 7a d3 f7 8b ee 6b 00 c5 3f dd 60 78 ae 20 d6 48 44 44 a5 35 cc d9 73 d1 ee c7 80 f3 7b 91 49 f8 65 a5 ab 93 a9 fc ec b1 cf eb fb 5f 88 47 e3 64 c6 e4 69 c4 f2 96 67 bb 28 ec 28 e2 ad f5 89 3a 3b 31 63 95 d5 5e df 4b 2d c9 95
dispASN1 end

2018年2月24日 (土)

Powershellワンライナーで実行ファイルのバージョンを取得

カレントディレクトリのexeとdllのバージョンを取得する。

PS C:\windows> Get-ChildItem *.dll,*.exe | % { "{0}`t{1}`t{2}" -F $_.Fullname, $_.VersionInfo.FileVersion, $_.VersionInf
o.productversion }
C:\windows\RtlExUpd.dll 1, 0, 4, 0      1, 0, 4, 0
C:\windows\twain_32.dll 1,7,1,3 1,7,1,0
C:\windows\AddCat.exe   1.0.0.1 1.0.0.1
C:\windows\bfsvc.exe    10.0.16299.15 (WinBuild.160101.0800)    10.0.16299.15
C:\windows\explorer.exe 10.0.16299.15 (WinBuild.160101.0800)    10.0.16299.15
C:\windows\HelpPane.exe 10.0.16299.15 (WinBuild.160101.0800)    10.0.16299.15
C:\windows\hh.exe       10.0.16299.15 (WinBuild.160101.0800)    10.0.16299.15
C:\windows\KSAIM64.exe  3,62,0,0        3,62,0,0
C:\windows\notepad.exe  10.0.16299.15 (WinBuild.160101.0800)    10.0.16299.15
C:\windows\regedit.exe  10.0.16299.15 (WinBuild.160101.0800)    10.0.16299.15
C:\windows\splwow64.exe 10.0.16299.15 (WinBuild.160101.0800)    10.0.16299.15
C:\windows\UN020914.EXE 1, 3, 8, 1      1, 3, 8, 1
C:\windows\winhlp32.exe 10.0.16299.15 (WinBuild.160101.0800)    10.0.16299.15
C:\windows\write.exe    10.0.16299.15 (WinBuild.160101.0800)    10.0.16299.15

Powershellで日時を取得

PS > get-date -format "yyyy/MM/dd HH:mm:ss.fff"
2018/02/24 18:42:31.239

より以前の記事一覧