【自我推薦】【報稅】健保卡元件 Ubuntu 20.04 軟體包 [論壇 - Ubuntu 與工具程式及軟體推薦]


正在瀏覽:   1 名遊客


 到底部   前一個主題   下一個主題  [無發表權] 請登錄或者註冊



【自我推薦】【報稅】健保卡元件 Ubuntu 20.04 軟體包
會員三級
註冊日期:
2009/8/27 21:33
所屬群組:
已註冊使用者
等級: 13
HP : 0 / 311
MP : 69 / 11678
EXP: 45
離線
現在離結束還有十幾天,報稅網頁還可以拿來測健保卡元件,有沒有人想要玩玩看的?

(原文連結: 健保卡元件 Ubuntu 20.04 軟體包 )

健保局的健保卡讀卡元件目前有 Linux 版本,但是使用 BASH 命令稿安裝,不受 deb 軟體包管理程式 apt/dpkg 管轄。小弟曾經將它改成了軟體包以方便管理,但是經過版本更替之後,舊版的元件就失效了。現在,小弟終於將新版做成軟體包,可以簡單的安裝,卸除時也不會在系統裡殘留某些檔案。

原本小弟想要將軟體包上傳到網路上來,給需要的人自由取用,但是免費託管網頁的伺服器不允許我這麼做。所以小弟將整個改製的過程寫成 BASH 命令稿上傳上來,有需要的人可以用命令稿自行生成軟體包,生成結果應當跟小弟的軟體包一模一樣。同時,有興趣的人可以自行閱讀命令稿,研究看看小弟怎做出這個軟體包的。

這個元件在安裝時,官方的安裝命令稿會在各個 Firefox 使用者資料中安裝憑證,使憑證能被 Firefox 承認。小弟為了重製這個流程,直接用 BASH 命令稿語言多寫了一個叫做 nhiicc-cert 的程式,可以很方便的安裝元件的憑證。有興趣的人可以在安裝後輸入 nhiicc-cert --help 來看簡單的說明,或是試試看它的幾項功能。如果 Firefox 的使用者帳號有變動,或是想要使用 Chrome 瀏覽器的人,也可以用這個小程式增刪憑證。比較簡單的方式是在命令列下達這樣的命令:

$ nhiicc-cert add -R -d $HOME


這個元件的軟體包可以讓 Ubuntu 20.04 版的使用者以 Firefox 進行健保卡認證,用於報稅或是使用健保卡網路服務。不過不知道為什麼,健保署提供的元件程式檔案裡面,安裝命令稿會安裝 libboost-all-dev 軟體包。這個軟體包引入了大約三百多 MiB 的軟體,其中真正被健保卡元件需要的可能寥寥無幾,小弟製作軟體包時原本想要幫這部份瘦身,但是實在沒有時間研究。所以軟體包在安裝的時候,可能會花掉不少時間下載安裝這些東西,請大家包涵。

另外,使用 Ubuntu 18.04 的朋友要失望了,由於舊版元件不再受到支援,而這個版本需要 GLIBC_2.29 版本,在 Ubuntu 18.04 啟動時會因為 Glibc 版本過低而自動關閉元件。小弟有考慮過強行將新版的函式庫檔案移植到軟體包中,可惜工程浩大,而且可能影響 Ubuntu 18.04 系統的穩定性,所以暫時擱置。

其他 Debian 衍生的發行版可能可以用,有興趣的人也可以裝裝看。

照例宣告:

1. 關於小弟在這個討論串發表的內容,由小弟撰寫的文字跟製作的圖片,使用創用CC-姓名標示方式授權。

2. 小弟為了提供大家方便使用而製作的軟體包,其中含有的軟體,著作權皆屬於其著作權人所有,依照原權利人提供的授權為準。

3. 在這個討論串跟小弟的健保卡元件軟體包中,小弟撰寫的程式碼,以 GPL-2.1 授權。

其他相關文章:
[使用心得]以 Ubuntu 18.04 版在 2018 年申報所得稅流程
[觀察報告]以網頁報稅在不同環境下的差異

6/19 17:24:04
應用擴展 工具箱
回覆: 【自我推薦】【報稅】健保卡元件 Ubuntu 20.04 軟體包
會員三級
註冊日期:
2009/8/27 21:33
所屬群組:
已註冊使用者
等級: 13
HP : 0 / 311
MP : 69 / 11678
EXP: 45
離線
生成軟體包的整個流程

請注意,目前的命令稿只有考慮 64 位元環境,32 位元的作業系統不適用。

首先,請先準備一個空的資料夾,並且用檔案管理程式打開它。
(Ubuntu 20.04 用的是「檔案」,但是小弟的 Ubuntu Mate 20.04 用的是 Caja)

然後在資料夾的空白處用滑鼠右鍵點一下,選「在終端機開啟」:

這時候就會開啟一個終端機視窗。

接著,把下面這些命令稿內容選取並複製起來:
#!/bin/bash
# ******* This script is licensed under            **********
# *******    the GNU General Public License 2.1    **********
# *******                         by Robert D. Wei **********

 function packing() {
  local Date='2022-06-19 UTC'

  local TgzFile=mLNHIICC_Setup.20220110.tar.gz
  local pakDir=mLNHIICC_Setup.20220530
  local NHIICCdir=usr/local/share/NHIICC
  local cmdPath=usr/local/bin
  local Server=cloudicweb.nhi.gov.tw/
  local Path=cloudic/system/SMC/
  local ZIPchecksum=a7a0780a2e8c492c50e6e35abfce0c75
        ZIPchecksum+=c78c4d792ca6b265810bf32aaae94941

  local pkgName=mlnhiicc
  local verNumber=20220530-0ubuntu0-20.04
  local chkSumStr

  if [ $( uname -m ) = x86_64 ] ; then
    local moduleStoreDir=x64
    local arch=amd64
    local size=2527
    local libsslPak=libssl1.1
  else
    local moduleStoreDir=x32
    local arch=i386
    local size=1828
    local libsslPak=libssl1.0
  fi

  local DEBpack=${pkgName}_${verNumber}_$arch.deb
  local TempDir BeginDir Sum

  if ! which ar > /dev/null ; then
    echo "Can not find 'ar', please install 'binutils' package." >&2
    return 1
  fi

  TempDir="$( mktemp -d )"
  BeginDir="$PWD"

  if [ -f $TgzFile ] ; then
    Sum="$( sha256sum $TgzFile )"
  fi

  if [ "${Sum%% *}" != "$ZIPchecksum" ] ; then
    rm -f $TgzFile
    wget https://$Server/$Path/$TgzFile
    Sum="$( sha256sum $TgzFile )"
  fi

  if [ "${Sum%% *}" != "$ZIPchecksum" ] ; then
     echo "Error when downloading software package!" >&2
     return 2
  fi

  cd "$TempDir"

  tar xf $BeginDir/$TgzFile

  mkdir -p control data/$NHIICCdir data/$cmdPath data/etc/init.d data/etc/rc5.d
  chmod 755 data/$NHIICCdir

  cp -a $pakDir/$moduleStoreDir/mLNHIICC data/$NHIICCdir
  chmod 755 data/$NHIICCdir/mLNHIICC
  cp -a $pakDir/web data/$NHIICCdir

  cat > data/etc/init.d/NHIICC << EOF
#!/bin/bash
### BEGIN INIT INFO
# Provides:        NHIICC
# Required-Start:  \$network
# Required-Stop:   \$network
# Default-Start:   5
# Default-Stop:    0 1 2 3 4
# Short-Description: NHIICC daemon
### END INIT INFO

source /lib/lsb/init-functions

case "\$1" in
  start)
    log_daemon_msg "Starting NHIICC daemon" "NHIICC"
    start-stop-daemon --start --quiet --exec /$NHIICCdir/mLNHIICC &
    log_end_msg \$?
    ;;
  stop)
    log_daemon_msg "Stopping NHIICC daemon" "NHIICC"
    start-stop-daemon --stop --exec /$NHIICCdir/mLNHIICC
    log_end_msg \$?
    ;;
  status)
    if  ps aux | grep NHIICC | grep -v grep > /dev/null ; then
        echo "NHIICC is running";
        exit 0;
    else
        echo "NHIICC is NOT running";
        exit 0;
    fi
    ;;
  force-reload|restart)
    \$0 stop
    \$0 start
    ;;
  *)
    echo "Usage: \$0 {start|stop|restart|force-reload}"
    exit 1
    ;;
esac

EOF
  chmod +x data/etc/init.d/NHIICC
  touch -d "$Date" data/etc/init.d/NHIICC

  cp -a $pakDir/cert data/$NHIICCdir

  if [ "$arch" = "amd64" ] ; then
    cd data/$NHIICCdir/cert/
    mv ca.crt ca-old.crt
    rm ca.key localhost.key localhost.csr localhost.crt NHIServerCert.crt \
       NHIServerCert.key NHIRootCA.crt
    cd -
  fi

  find data/$NHIICCdir/{cert,web} -type f -name '._*' -exec rm '{}' \;

  cat > data/$cmdPath/nhiicc-cert << EOF
#!/bin/bash
# ******* This script is licensed under            **********
# *******    the GNU General Public License 2.1    **********
# *******                         by Robert D. Wei **********

CertFile="/usr/local/share/NHIICC/cert/NHIRootCA.crt"
CertName="NHI.Root.CA"

function main() {

  eval \$( analysis_arguments "\$@" )

  if \$ask_help ; then
    show_help

  elif \$for_all ; then
    modify_cert_on_all \$act

  elif \$has_dir ; then
    modify_cert_in_directory \$act "\$directory" \$recursive

  else
    modify_cert_in_users_home \$act "\$HOME"

  fi
}


function analysis_arguments() {
  local act ask_help=false for_all=false has_dir=false directory recursive=false
  local is_root myID="\$( id -u )" x valu

  test "\$myID" = "0" && is_root=true || is_root=false

  if [ "\$1" = "add" ] ; then
    act=add
  elif [ "\$1" = "remove" ] ; then
    act=remove
  elif [ "\$1" = "" ] || [ "\$1" = "-h" ] || [ "\$1" = "--help" ] ; then
    ask_help=true
  else
    echo "「\$1」命令不存在。" 1>&2
    show_help 1>&2
    echo exit 1 ; return 1
  fi
  shift

  while [ \$# -gt 0 ] ; do
    case "\$1" in
     --all)
      if \$is_root ; then
        for_all=true
        shift
      else
        echo '需要有根帳號(root)的權限才能為所有人管理憑證。' 1>&2
        exit 1
      fi
      ;;

     -d)
      shift
      directory="\$1"
      has_dir=true
      shift
      ;;

     -R)
      recursive=true
      shift
      ;;

     *)
      echo "無法解釋參數「\$1」。" 1>&2
      exit 1
    esac
  done

  if \$for_all && ( \$has_dir || \$recursive ); then
    echo "參數「--all」不能和其他參數同時使用。" 1>&2
    echo exit 1 ; return 1
  elif \$has_dir && ! [ -d "\$directory" ] ; then
    echo "「\$4」不是資料夾。" 1>&2
    echo exit 1 ; return 1
  elif \$has_dir && \\
       [ "\$( stat -c '%u' \$directory )" != "\$myID" ] && ! is_root ; then
    echo "「\$directory」資料夾不屬於你,請改用根帳號(root)權限進行作業。" 1>&2
    echo exit 1 ; return 1
  elif \$recursive && ! \$has_dir ; then
    echo "參數「-R」必須和參數「-d ...」同時使用。" 1>&2
    echo exit 1 ; return 1
  fi

  echo -n "local "
  for x in act ask_help for_all has_dir directory recursive ; do
     eval valu=\\$\$x
     echo -n \$x="\"\$valu\" "
  done
}

function show_help() {

  echo -e "\n命令格式:\n"
  echo -e "\tnhiicc-cert add|remove\n"
  echo -e "\t\t在自己的 nss 資料庫和 firefox 的預設帳號中增刪憑證。\n"
  echo -e "\tnhiicc-cert add|remove --all\n"
  echo -e "\t\t在所有人的家目錄中增刪憑證。(需要 root 權限)\n"
  echo -e "\tnhiicc-cert add|remove [-R] [-d 資料夾名稱]\n"
  echo -e "\t\t在指定的資料夾中增刪憑證,使用「-R」會包含所有子資料夾。\n"
  echo -e "\tnhiicc-cert [-h|--help]\n"
  echo -e "\t\t使用說明。\n"
  echo -e "\t注意:後方的參數會覆蓋前方相同參數的設定。\n"
}

function modify_cert_on_all() {
  local act=\$1 home_dir recursive=true

  for home_dir in \$( print_all_home_directory ) ; do
    echo "\${act}: Work on \$home_dir"
    test \$act = add \\
      && modify_cert_in_users_home add "\$home_dir" \\
      || modify_cert_in_directory remove "\$home_dir" \$recursive
  done
}

function modify_cert_in_directory() {
  local act=\$1 directory="\$2" recursive="\$3" certDir

  for certDir in \$(
    ! \$recursive && echo "\$directory" \\
                 || ( find "\$directory" -name "cert[89].db" 2> /dev/null \\
                        | sed s/cert..db\$// | sort | uniq ) ) ; do
    modify_cert_in_this_database \$act "\$certDir"
  done
}

function modify_cert_in_users_home() {
  local act=\$1 home_dir="\$2" certDir ffxPath="\$2/.mozilla/firefox"

  for certDir in \$( 
    find "\$home_dir/.pki" -name nssdb 2> /dev/null
    test \$act = add \\
      && ( grep "^Default=.." "\$ffxPath/profiles.ini" \\
            | sed "s|^Default=|\$ffxPath/|" ) \\
      || ( grep "^Path=" "\$ffxPath/profiles.ini" \\
            | sed "s|^Path=|\$ffxPath/|" ) ) ; do
    modify_cert_in_this_database \$act "\$certDir"
  done
  
}

function print_all_home_directory() {
  local lineData

  grep -v '^nobody:' /etc/passwd | cut -d : -f 3,6 \\
   | while read lineData ; do
      if [ \${lineData%%:*} -ge 1000 ] ; then
        echo "\${lineData#*:}"
      fi
  done
}

function modify_cert_in_this_database() {
  local act=\$1 certDir="\$2"
  local not_sql=true

    if [ -f "\$certDir/cert9.db" ] ; then
      if [ \$act = add ] ; then
        echo "Add to sql:\$certDir"
        certutil -A -n "\$CertName" -t "TC,," -i "\$CertFile" -d sql:"\$certDir"
      else
        certutil -L -n "\$CertName" -d sql:"\$certDir" >/dev/null 2>&1 \\
        && (  echo "Remove from sql:\$certDir" ; \\
              certutil -D -n "\$CertName" -d sql:"\$certDir" )
      fi
      not_sql=false
    fi
    
    if [ \$act = remove ] || \$not_sql ; then
      if [ \$act = add ] ; then
        echo "Add to dbm:\$certDir"
        certutil -A -n "\$CertName" -t "PCT,Cu,Tu" -i "\$CertFile" -d dbm:"\$certDir"
      else
        certutil -L -n "\$CertName" -d dbm:"\$certDir" >/dev/null 2>&1 \\
        && (  echo "Remove from dbm:\$certDir" ; \\
              certutil -D -n "\$CertName" -d dbm:"\$certDir" )
      fi
    fi
}

main "\$@"

EOF
  chmod 755 data/$cmdPath/nhiicc-cert
  touch -d "$Date" data/$cmdPath/nhiicc-cert

  touch -d "$Date" $( find data -type d )





  cat > control/control << EOF
Package: $pkgName
Version: $verNumber
Architecture: $arch
Maintainer: Freedman
Installed-Size: $size
Depends: openssl, pcscd, libnss3-tools, libc6, $libsslPak, libssl-dev, ca-certificates, libboost-all-dev, unbound-anchor
Section: misc
Priority: optional
Homepage: https://cloudicweb.nhi.gov.tw/cloudic/system/SMC/mEventesting.htm
Description: $pkgName for National Health Insurance Card using
 This driver is sliced out for Ubuntu form official driver pack and then
 packed into .deb file through shell commands.
EOF

  cd data
  md5sum $( find -type f | sed 's|^./||' | sort ) > ../control/md5sums
  cd - > /dev/null






  cat > control/preinst << EOF
#!/bin/sh

service NHIICC stop 2> /dev/null
service mLNHIICC stop 2> /dev/null
killall -q mLNHIICC 2> /dev/null || true
EOF





  cat > control/postinst << EOF
#!/bin/sh

ln -s /etc/init.d/NHIICC /etc/rc5.d/S50NHIICC

grep localhost /etc/hosts | grep -q 127.0.0.1
if [ ! $? -eq 0 ] ; then
    echo  \ \ >> /etc/hosts
    echo 127.0.0.1 localhost >> /etc/hosts
fi

EOF

  if [ "$arch" = "amd64" ] ; then
    cat >> control/postinst << EOF
org=nhi-localhost-ca
domain=localhost

trust anchor --remove /$NHIICCdir/cert/ca-old.crt || true

openssl genpkey -algorithm RSA -out /$NHIICCdir/cert/ca.key
openssl req -x509 -key /$NHIICCdir/cert/ca.key \\
    -out /$NHIICCdir/cert/ca.crt -subj "/CN=\$org/O=\$org"

openssl genpkey -algorithm RSA -out /$NHIICCdir/cert/"\$domain".key
openssl req -new -key /$NHIICCdir/cert/"\$domain".key \\
    -out /$NHIICCdir/cert/"\$domain".csr \\
    -subj "/CN=\$domain/O=\$org"

tempFil="\$( mktemp )"
cat > "\$tempFil" << END
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
subjectAltName = DNS:\$domain
END

openssl x509 -req -in /$NHIICCdir/cert/"\$domain".csr -days 18263 \\
    -out /$NHIICCdir/cert/"\$domain".crt \\
    -CA /$NHIICCdir/cert/ca.crt \\
    -CAkey /$NHIICCdir/cert/ca.key -CAcreateserial \\
    -extfile "\$tempFil"

rm "\$tempFil"

trust anchor /$NHIICCdir/cert/ca.crt

cp -a /$NHIICCdir/cert/localhost.crt \\
   /$NHIICCdir/cert/NHIServerCert.crt
cp -a /$NHIICCdir/cert/localhost.key \\
   /$NHIICCdir/cert/NHIServerCert.key
cp -a /$NHIICCdir/cert/ca.crt \\
   /$NHIICCdir/cert/NHIRootCA.crt

EOF
  fi

cat >> control/postinst << EOF
/$cmdPath/nhiicc-cert add --all
nohup bash -c '
  while service NHIICC status 2>&1 | grep "could not be found" > /dev/null ; do
    sleep 0.3
  done
  service NHIICC start &' > /dev/null &
EOF

  cp control/preinst control/prerm

  echo -e "\nrm /etc/rc5.d/S50NHIICC" >> control/prerm

  if [ "$arch" = "amd64" ] ; then
    cat >> control/prerm << EOF

/$cmdPath/nhiicc-cert remove --all

trust anchor --remove /$NHIICCdir/cert/ca.crt

rm /$NHIICCdir/cert/NHIRootCA.crt /$NHIICCdir/cert/NHIServerCert.key
rm /$NHIICCdir/cert/NHIServerCert.crt
org=nhi-localhost-ca
domain=localhost
rm /$NHIICCdir/cert/"\$domain".crt /$NHIICCdir/cert/"\$domain".csr
rm /$NHIICCdir/cert/ca.crt /$NHIICCdir/cert/ca.key

EOF
  fi


  cat > control/postrm << EOF
#!/bin/sh

grep -q iccert.nhi.gov.tw /etc/hosts;
if [ \$? -eq 0 ] ; then
    sed -i '/iccert\.nhi\.gov\.tw/d' /etc/hosts
fi
EOF

  chmod +x control/p*

  touch -d "$Date" control/*

  cd control
  tar -H ustar --sort=name --owner=root:0 --group=root:0 \
      -cvf ../control.tar $( ls )
  cd - > /dev/null

  cd data
  tar -H ustar --sort=name --owner=root:0 --group=root:0 \
      -cvf ../data.tar  $( ls -d )
  cd - > /dev/null

  touch -d "$Date" control.tar data.tar
  md5sum control.tar data.tar
  gzip -c control.tar > control.tar.gz
  xz -c data.tar > data.tar.xz
  md5sum control.tar.gz data.tar.xz
  echo 2.0 > debian-binary

  ar cDr $BeginDir/$DEBpack \
         debian-binary control.tar.gz data.tar.xz

  cd $BeginDir
  rm -r $TempDir
  md5sum $DEBpack
  chkSumStr="$(sha256sum $DEBpack)"
  echo "$chkSumStr"
  test "${chkSumStr%% *}" = "1b176020ecc0366d444d4437f75e140895c34aee7e1d85627a7379354080f411" \
    && touch -d '2022-06-19 13:39:48.423851937 +0800' $DEBpack \
    || (echo Checksum not match! 1>&2 ; false)
 }

 packing && unset packing || ( unset packing ; false)



接著回到剛剛開啟的終端機視窗,用滑鼠右鍵在視窗中點一下,選「貼上」:


接下來就會開始下載健保卡元件程式,並且生成軟體包。當然有興趣的朋友也可以把命令稿貼到文字編輯器中存檔,然後改用執行檔案的方式執行,或是自行研究修改。

等到軟體包生成好之後,畫面應該像是這樣:

小弟讓命令稿列出生成過程中各個檔案的雜湊值,你的結果應該跟小弟的一樣。如果你看到的雜湊數字跟圖片裡的不一樣,那有可能生成中間出了一點小弟沒想到的差異,也許沒有影響,但也可能你的軟體包會不能使用。

一切順利的話,你可以在資料夾當中找到兩個檔案,一個是原本的程式壓縮檔,另一個就是剛剛生成的軟體包(通常在左邊)。現在用滑鼠點兩下軟體包就可以安裝了:

附件:



png  01.png (82.13 KB)
16527_62aeec48c8e7e.png 632X500 px

png  02.png (37.09 KB)
16527_62aeed832016b.png 510X493 px

png  04.png (59.46 KB)
16527_62aeee1431a34.png 493X414 px

png  03.png (105.32 KB)
16527_62aef20b5bdb0.png 642X235 px

6/19 17:40:44
應用擴展 工具箱
回覆: 【自我推薦】【報稅】健保卡元件 Ubuntu 20.04 軟體包
會員五級
註冊日期:
2009/10/29 4:50
所屬群組:
已註冊使用者
等級: 41
HP : 203 / 1019
MP : 922 / 37723
EXP: 77
離線
感謝!

6/19 20:19:37
應用擴展 工具箱
回覆: 【自我推薦】【報稅】健保卡元件 Ubuntu 20.04 軟體包
會員五級
註冊日期:
2012/4/22 10:50
所屬群組:
已註冊使用者
等級: 36
HP : 175 / 876
MP : 625 / 26090
EXP: 7
離線
親愛的樓主,

容許我稍微地歪樓一下,

我比較好奇的是,

從您提供的圖片,

我想了解的是,您搭配的

* gtk-theme
* icon-theme
* cursor-theme

分別是那個「theme」

是否能提供相關的「關鍵字」或「網址」提供參考

哈,我是否搞錯此討論串的重點


6/19 21:26:05
應用擴展 工具箱
回覆: 【自我推薦】【報稅】健保卡元件 Ubuntu 20.04 軟體包
會員三級
註冊日期:
2009/8/27 21:33
所屬群組:
已註冊使用者
等級: 13
HP : 0 / 311
MP : 69 / 11678
EXP: 45
離線
samwhelp 寫到:
……(恕刪)
* gtk-theme
* icon-theme
* cursor-theme
分別是那個「theme」
是否能提供相關的「關鍵字」或「網址」提供參考
哈,我是否搞錯此討論串的重點

是 Musicha 音創筆電第一代的原始設定
小弟不是音樂創作人,當時是差不多該換電腦了,順便給社群朋友捧場
出廠時電腦的桌面已經做了很多設計,小弟就不再更改了
保留作為這位朋友的創業紀念品。
他的網站在這:
Musicha 音創筆電 - 創作就是如此優雅而豐富~

6/19 21:57:12
應用擴展 工具箱
回覆: 【自我推薦】【報稅】健保卡元件 Ubuntu 20.04 軟體包
會員五級
註冊日期:
2012/4/22 10:50
所屬群組:
已註冊使用者
等級: 36
HP : 175 / 876
MP : 625 / 26090
EXP: 7
離線
了解,感謝樓主的回覆


6/19 22:12:58
應用擴展 工具箱


 [無發表權] 請登錄或者註冊


可以查看帖子.
不可發帖.
不可回覆.
不可編輯自己的帖子.
不可刪除自己的帖子.
不可發起投票調查.
不可在投票調查中投票.
不可上傳附件.
不可不經審核直接發帖.