ABAP:HmacSha関連

知的好奇心でVBAに続きABAPでも書いてみました。

驚いたことに「CL_ABAP_HMAC」という見たまんまのクラスを用意していてくれて素直に叩けばおしまいでした。
また、同クラス内にはコード変換、形式変換等のユーティリティメソッドも内包していて至れり尽くせりでした。

VBAとくらべて拍子抜けするほど簡単です。

対応するアルゴリズムは以下の通り
・'MD5'
・'SHA1' or 'SHA-1'
・'SHA256' or 'SHA-256'
・'SHA384' or 'SHA-384'
・'SHA512' or 'SHA-512'

24行目の引数を変えるだけで上記アルゴリズムに対応します。
やっぱ、ABAPって生産性高いなぁ〜って思います。

ソースコードをどうぞ〜!

L001:* 呼び出し元は以下の通り
L002: DATA VALUE TYPE STRING.
L003: PERFORM GET_HMACSHA512
L004: USING
L005: 'key'
L006: 'text'
L007: CHANGING
L008: VALUE.
L009:
L010:*-----------------------------------------------------------------------
L011:* 暗号化する
L012:* Key 秘密鍵
L013:* text メッセージ文字列
L014:*-----------------------------------------------------------------------
L015:FORM GET_HMACSHA512
L016: USING
L017: KEY TYPE STRING
L018: TEXT TYPE STRING
L019: CHANGING
L020: VALUE TYPE STRING.
L021:*-----------------------------------------------------------------------
L022: DATA(LO_HMAC) = CL_ABAP_HMAC=>GET_INSTANCE(
L023: EXPORTING
L024: IF_ALGORITHM = 'SHA-512'
L025: IF_KEY = CL_ABAP_HMAC=>STRING_TO_XSTRING( EXPORTING IF_INPUT = KEY ) ).
L026: LO_HMAC->UPDATE( IF_DATA = CL_ABAP_HMAC=>STRING_TO_XSTRING( EXPORTING IF_INPUT = TEXT ) ).
L027: LO_HMAC->FINAL( ).
L028: VALUE = LO_HMAC->TO_STRING( ).
L029: TRANSLATE VALUE TO LOWER CASE.
L030:ENDFORM.
L031:

検索キーワード
HMAC
HMACMD5
HMAC MD5
HMACRIPEMD160
HMAC RIPEMD160
HMACSHA1
HMAC SHA1
HMACSHA256
HMAC SHA256
HMACSHA384
HMAC SHA384
HMACSHA512
HMAC SHA512
ABAP
ABAP Object
CL_ABAP_HMAC

以上

VBA HmacSha関連

VBAネタです。

HMACSHAをExcel VBAで取得する。

なんでそんなもんが必要なのか?
それは置いておいて...。

いろいろインターネットを調べました。
・日本語以外に、英語、ロシア語まで出てきました。
・標準モジュールをインポートして、これをたたく方法なんかもありました。
 →そもそもおかしい結果を戻すものだったり〜
 →微妙に表面化しなさそうなバグを含んでいたり〜

HMACSHA256が動くコードはいくらでも見つかりました。
 →Amazonを利用するときに必要らしい。
でも僕はどうしてもHMACSHA512が必要なんです。

こういう時は本家マイクロソフトの開発者サイトを参照
https://msdn.microsoft.com/ja-jp/library/system.security.cryptography.hmac
そしてこのクラス群はVBAから呼べるようになっているらしい。

ならば以下のようなことはやめよう。単純に格好悪いから△
・自分でいろいろ作ったり〜
・野良コードを使ったり〜

やっぱり格好良く本家マイクロソフト様のライブラリをたたきたい!!!
 →Microsoft Updateでバグ対応してくれるし〜

そんなことで放課後を活用して試行錯誤1週間かかりました。ちょっと自信があります。
 →参照設定とか不要です〜
 →野良標準モジュールとか不要です〜
 →答え合わせも大体しました〜
https://en.wikipedia.org/wiki/HMAC#Examples

とりあえず〜
これがなかなか無くて苦労したので〜
HMACSHAの入力と出力例をどうぞ〜(多分合ってます)
入力
・Key:"key"
・Text:"text"

出力
・HMACMD5:"d0ca6177c61c975fd2f8c07d8c6528c6"
・HMACRIPEMD160:"4d8346547b3779dc51f53313db96061c80292806"
・HMACSHA1:"369e2959eb49450338b212748f77d8ded74847bb"
・HMACSHA256:"6afa9046a9579cad143a384c1b564b9a250d27d6f6a63f9f20bf3a7594c9e2c6"
・HMACSHA384:"57c1323ef95b53bc7371d770cd31419d104cb5bcdb5ca6372364246f1884180657d5429860ac72ce19f9109d38ad54b6"
・HMACSHA512:"b585312acdd38ec13f13bb4cba35a75473f32b6ae4a0303926815bd43d7a2631516b2b031f34d89eda853e948d5057de54a880c16697242dbe6a1ad994bc4e5d"

そして〜ソースコードをどうぞ〜!
 →引数に初期値を与えています。→答え合わせしやすいように〜
 →30行目を必要に応じて書き換えてね〜それだけでばっちりだから!
 →関数名も書き換えるよね〜(笑)

L001:'=======================================================================
L002:'呼び出し元
L003:'=======================================================================
L004:Private Sub Example()
L005: Debug.Print HmacSha512("key", "text")
L006:End Sub
L007:'=======================================================================
L008:
L009:'=======================================================================
L010:'暗号化する
L011:'Key 秘密鍵
L012:'text メッセージ文字列
L013:'=======================================================================
L014:Private Function HmacSha512( _
L015: Optional key As String = "", _
L016: Optional text As String = "" _
L017: ) As String
L018:'-----------------------------------------------------------------------
L019:'キーとテキストのバイト配列を作成する
L020: Dim utf8 As Object
L021: Set utf8 = CreateObject("System.Text.UTF8Encoding")
L022: Dim keyEncodedBytes() As Byte
L023: keyEncodedBytes = utf8.Getbytes_4(key)
L024: Dim textEncodedBytes() As Byte
L025: textEncodedBytes = utf8.Getbytes_4(text)
L026: Set utf8 = Nothing
L027:
L028:'バイト配列のハッシュ値を取得する
L029: Dim hmac As Object
L030: Set hmac = CreateObject("System.Security.Cryptography.HMACSHA512")
L031: hmac.key = keyEncodedBytes
L032: Dim hashEncodedBytes() As Byte
L033: hashEncodedBytes = hmac.ComputeHash_2(textEncodedBytes)
L034: Set hmac = Nothing
L035:
L036:'文字列に変換する
L037: Dim hashEncodedByte As Variant
L038: Dim hash As String
L039: For Each hashEncodedByte In hashEncodedBytes
L040: hash = hash & Right("0" & Hex(hashEncodedByte), 2)
L041: Next
L042: HmacSha512 = LCase(hash)
L043:
L044:End Function
L045:'===============================================================================

検索キーワード
HMAC
HMACMD5
HMAC MD5
HMACRIPEMD160
HMAC RIPEMD160
HMACSHA1
HMAC SHA1
HMACSHA256
HMAC SHA256
HMACSHA384
HMAC SHA384
HMACSHA512
HMAC SHA512
Excel VBA
Access VBA
VB6
Visual Basic 6.0
WSH
Windows Script Host
dotNet
Amazon Web Services

以上

親戚のPCの保守

今更ネタです。
良い時代になったと思いました。

義理の両親のPCの保守をしています。
PCの調子が悪くなると、(主にマルウェアをインストールしてしまう)
PCの調子を見てほしいとのご連絡が来ます。

今までは、息子を見せに行くついでに、
怪しいアプリケーションを削除しに行っていました。
ただ、義理の両親が遠慮するので先延ばしになってしまうことが多かったのです。

で、Windows標準機能に、リモートアシスタンスというのがあるので、
検証したところなんかうまくいかないまま放置していたのですが、
フリーソフトで同様の機能を持ったものがあるようで、
使ってみたところ、ブロードバンドルーターをあっさり越えてくれて正常動作しました。
特別な操作は一切していません。

「Anydesk」

個人利用の場合無償で使用できるとのこと。
今回実家へ行かずしてマルウェアのアンインストールできました。
(一部クリックできないボタンがあり、義理の両親に手伝ってもらいました)

便利にはなったのですが、義理の両親宅へ行く頻度が減ってしまうのが、
悩みになりそうです。

Yahoo!メールの広告メール等を一括解除・一括無効化する。

今日は少し仕事から外れて、別のことを話題にします。
Yahoo!メール」使っていますか?
IMAP対応なので、パソコン、スマートフォン等々で使えるので便利ですよね。
私も首まで浸かっています。(笑)

だた...少し困っているのは広告メールが多いんです。
更に、広告メールに種類がいくつか(数えたら46種類ありました)あって、
これらを広告メールが配信されるたびに、
メール内の解除リンクから解除していると、
非常に手間がかかるのが困りものなんです。
そこで、一括解除する方法を調べてみましたが、情報が少し古いようで戸惑いました。
だいたいこんな感じ。

                                                                                                                                              • -

古い情報:
Yahoo!JAPANトップページ」→「登録情報」
右下の方の「おすすめ情報メール」あります)から一括解除できる。

                                                                                                                                              • -

時代は変わって...(笑)
Yahoo!のページ構成が変わってしまったようです。
自身でイロイロ試行錯誤した結果、こんな感じで広告メールをお断りすることが出来るようです。

                                                                                                                                              • -

新しい(笑)情報(パソコンの場合):
Yahoo!トップページより(もちろん、予め、Yahoo! IDでログオンしておいてください)

右側の「こんにちは、xxxxxxxxさん」の、
右8cm下1cm位のところにある「登録情報」リンクをクリックする。

右下の「プライバシー」→「プライバシー設定」リンクをクリックする。

「広告設定」→「設定する」リンクをクリックする。
「広告などへの行動履歴の利用」をクリックして「OFF(水色→白)」にする。
下にある「プライバシー設定」リンクをクリックして戻る。

「メール設定」→「Yahoo! JAPANからのおすすめメール」→「設定する」リンクをクリックする。
再度パスワードを求められるので入力する。
「配信の登録・解除」のず〜っと下の「すべての選択を解除」リンクをクリックする。
「設定を変更」ボタンをクリックする。
ブラウザの戻るボタンを3回クリックして戻る。

「メール設定」→「Yahoo!ダイレクトオファー」→「設定する」リンクをクリックする。
※※「Yahoo!ダイレクトオファー」を無効化すると、
メールクライアント等からYahoo!メールを利用出来なくなるので注意が必要!!
「登録」→「登録しない」ラジオボタンをクリックする。
「終了」ボタンをクリックする。

「メール設定」→「Yahoo!メールの便利機能と広告最適化」リンクをクリックする。
「無効にする」ボタンをクリックする。
ブラウザの戻るボタンをクリックして戻る。

「各アプリケーションでのデータ利用」→「設定する」リンクをクリックする。
利用していればリンクを表示するのでそれぞれ無効もしくは解除する。
ブラウザの戻るボタンを何回かクリックして戻る。

「外部企業へのデータ提供設定」→「設定する」リンクをクリックする。
以下についてそれぞれ「無効化する」ボタンをクリックする。
・「カルチュア・コンビニエンス・クラブ株式会社」(Tポイントと連携している場合のみ)
・「バリューコマース株式会社」
※「無効化する」ボタンが「有効化する」ボタンに切り替わっていればOK!
ブラウザの戻るボタンを何回かクリックして戻る。

再び
Yahoo!トップページより(もちろん、予め、Yahoo! IDでログオンしておいてください)
画面左の「ショッピング」リンクをクリックする。
画面右の「メール配信」→「申し込み・変更・停止 」リンクをクリックする。
(「メール配信」を文字列検索すると見つけやすい)
各「配信設定の変更」リンクをクリックする。
一旦どれでも良いので「配信先メールアドレス」を選択する。
「すべて停止」リンクをクリックする。
「確定する」ボタンをクリックする。
Yahoo!ショッピングトップページへ」ボタンをクリックする。
再び、画面右の「メール配信」→「申し込み・変更・停止 」リンクをクリックする。
...

                                                                                                                                              • -

以上です。



検索キーワード:
yahoo.co.jp
mail.yahoo.co.jp
Yahoo Japan
Yahoo!メール
ヤフーメール
広告
広告メール
プライバシー設定
広告設定
Yahoo! JAPANからのおすすめメール
Yahoo!ダイレクトオファー
Yahoo!メールの便利機能と広告最適化
各アプリケーションでのデータ利用
外部企業へのデータ提供設定
カルチュア・コンビニエンス・クラブ株式会社
バリューコマース株式会社
一括解除
解除
一括無効化
無効化

ABAP New open SQL:INTO TABLEの記述場所について

私の悩みを聞いてください☆

Open SQLを記述していると、「INTO TABLE」をどこに書くか悩むことが多々ありました。
いままで私は、SELECT xxxx INTO TABLE xxxx FROM 〜の順番で書いていました。
理由として、項目および項目の並び順は、格納する内部テーブルと密接に関連するので、
つながりが深いものは可能な限り近くに記述するほうが、
コードが読みやすく保守性も良くなると考えていたからです。

しか〜し(笑)、数週間前から改めます。



INTO TABLE xxxxは最後に書く!!!



理由としては、ABAP 7.5になってからいくつか機能拡張(SQL関数、UNION句等)して、
これらを使うと、INTO TABLE xxxxは最後に書かないと...(これから先が重要!!)



文法エラーで有効化できない!!!



もう一度言います。



INTO TABLE xxxxは最後に書く!!!



つい先ほどまで、過去に書いた記事のソースコードをすべて書き直しました。(ふ〜ぅ)
でもさぁ〜本当に最後に書くの普及するのかなぁ〜!?
(Classic Open SQLだと、エラーだし...)

しつこいけれど、もう一度言います。



INTO TABLE xxxxは最後に書く!!!



でした☆
今日は「!」が多いなぁ〜。


検索キーワード
ABAP
ABAP 7.4
ABAP 7.40
ABAP 7.5
ABAP 7.50
SQL
Open SQL
New Open SQL
Classic Open SQL
SAP HANA
Code to Data
Code Pushdown

以上

ABAP New open SQL:SQL関数拡張(1) on ABAP 7.50

ABAP New open SQLSQL関数拡張(1) on ABAP 7.50

今回は、「SQL関数拡張(1) on ABAP 7.50」ということで、CONCAT()を使った例を示す。
購買伝票明細EKPOを使って、
購買伝票番号と購買伝票の明細番号の文字列結合と、
プラントと保管場所の文字列結合をしてみる。
そして、区切り文字として「-」を付加する。

購買伝票番号と購買伝票の明細番号は両方とも必須項目なのでシンプルになるが、
プラントと保管場所については保管場所が任意項目のため、
プラントのみの場合は区切り文字として「-」を取るようにする。

早速SELECT文を...

L085:  SELECT
L086:      CONCAT( CONCAT( ti0~ebeln,'-' ),ti0~ebelp ) AS c1,
L087:      CASE
L088:        WHEN ti0~werks = @space AND ti0~lgort = @space THEN @space
L089:        WHEN ti0~werks <> @space AND ti0~lgort = @space THEN ti0~werks
L090:        WHEN ti0~werks = @space AND ti0~lgort <> @space THEN CONCAT( '     ', ti0~werks )
L091:        ELSE CONCAT( CONCAT( ti0~werks,'-' ),ti0~lgort ) END AS c2,
L092:      ti0~werks,
L093:      ti0~lgort
L094:    FROM ekpo AS ti0
L095:    ORDER BY
L096:      ti0~ebeln,
L097:      ti0~ebelp
L098:    INTO TABLE @DATA(lt_data).

購買伝票番号と購買伝票の明細番号はL086に記述している。
SQL関数は入れ子にして使うことも可能である。
3個以上の項目を結合するときはこんな感じ。

プラントと保管場所はL087-L091に記述している。
プラントは必須項目であるが今回は任意項目として記述してみた。
よって4通りのパターンがあるためそれぞれ記述している。
L092-L093は参考として素のデータを出力している。

今回気づいたのだが、
「INTO TABLE〜」は最後の行に書く必要がある。(エラーで有効化できなかった)
ABAP 7.50になって、ABAP CDSの文法を意識しているのかもしれない。
(近々アップロード済みのソースを修正します)→修正しました。2017-10-18

                                                                                                                                              • -

L001:*&---------------------------------------------------------------------*
L002:*& Report Y_SQL_CONSOLE
L003:*&---------------------------------------------------------------------*
L004:*&
L005:*&---------------------------------------------------------------------*
L006:REPORT y_sql_console.
L007:
L008:*-----------------------------------------------------------------------
L009:* グローバル変数
L010:*-----------------------------------------------------------------------
L011:DATA gv_subrc TYPE sy-subrc.
L012:
L013:*-----------------------------------------------------------------------
L014:* 選択画面
L015:*-----------------------------------------------------------------------
L016:*
L017:DATA gv_char1 TYPE char10.
L018:TYPES gtrt_char1 LIKE RANGE OF gv_char1.
L019:SELECT-OPTIONS s_char1 FOR gv_char1.
L020:*
L021:DATA gv_char2 TYPE char10.
L022:TYPES gtrt_char2 LIKE RANGE OF gv_char2.
L023:SELECT-OPTIONS s_char2 FOR gv_char2.
L024:*
L025:DATA gv_numc1 TYPE numc08.
L026:TYPES gtrt_numc1 LIKE RANGE OF gv_numc1.
L027:SELECT-OPTIONS s_numc1 FOR gv_numc1.
L028:*
L029:DATA gv_numc2 TYPE numc08.
L030:TYPES gtrt_numc2 LIKE RANGE OF gv_numc2.
L031:SELECT-OPTIONS s_numc2 FOR gv_numc2.
L032:*
L033:DATA gv_dats1 TYPE dats.
L034:TYPES gtrt_dats1 LIKE RANGE OF gv_dats1.
L035:SELECT-OPTIONS s_dats1 FOR gv_dats1.
L036:*
L037:DATA gv_dats2 TYPE dats.
L038:TYPES gtrt_dats2 LIKE RANGE OF gv_dats2.
L039:SELECT-OPTIONS s_dats2 FOR gv_dats2.
L040:*
L041:DATA gv_tims1 TYPE tims.
L042:TYPES gtrt_tims1 LIKE RANGE OF gv_tims1.
L043:SELECT-OPTIONS s_tims1 FOR gv_tims1.
L044:*
L045:DATA gv_tims2 TYPE tims.
L046:TYPES gtrt_tims2 LIKE RANGE OF gv_tims2.
L047:SELECT-OPTIONS s_tims2 FOR gv_tims2.
L048:
L049:*-----------------------------------------------------------------------
L050:* 主処理
L051:*-----------------------------------------------------------------------
L052:START-OF-SELECTION.
L053:  PERFORM start_of_selection
L054:    USING
L055:      s_char1
L056:      s_char2

L057:      s_numc1
L058:      s_numc2

L059:      s_dats1
L060:      s_dats2

L061:      s_tims1
L062:      s_tims2

L063:    CHANGING
L064:      gv_subrc.
L065:
L066:*-----------------------------------------------------------------------
L067:* サブルーチン
L068:*-----------------------------------------------------------------------
L069:FORM start_of_selection
L070:    USING
L071:      urt_char1 TYPE gtrt_char1
L072:      urt_char2 TYPE gtrt_char2
L073:      urt_numc1 TYPE gtrt_numc1
L074:      urt_numc2 TYPE gtrt_numc2
L075:      urt_dats1 TYPE gtrt_dats1
L076:      urt_dats2 TYPE gtrt_dats2
L077:      urt_tims1 TYPE gtrt_tims1
L078:      urt_tims2 TYPE gtrt_tims2
L079:    CHANGING
L080:      cv_subrc TYPE sy-subrc.
L081:*-----------------------------------------------------------------------
L082:* ここに、SQL文を書いてね☆
L083:* 格納する内部テーブルは、lt_dataにしてね☆
L084:* lt_dataをインライン定義すると、楽ちんだ☆
L085:  SELECT
L086:      CONCAT( CONCAT( ti0~ebeln,'-' ),ti0~ebelp ) AS c1,
L087:      CASE
L088:        WHEN ti0~werks = @space AND ti0~lgort = @space THEN @space
L089:        WHEN ti0~werks <> @space AND ti0~lgort = @space THEN ti0~werks
L090:        WHEN ti0~werks = @space AND ti0~lgort <> @space THEN CONCAT( '     ', ti0~werks )
L091:        ELSE CONCAT( CONCAT( ti0~werks,'-' ),ti0~lgort ) END AS c2,
L092:      ti0~werks,
L093:      ti0~lgort
L094:    FROM ekpo AS ti0
L095:    ORDER BY
L096:      ti0~ebeln,
L097:      ti0~ebelp
L098:    INTO TABLE @DATA(lt_data).
L099:*-----------------------------------------------------------------------
L100:  TRY.
L101:      cl_salv_table=>factory(
L102:        IMPORTING
L103:          r_salv_table = DATA(lo_alv)
L104:        CHANGING
L105:          t_table  = lt_data ).
L106:    CATCH cx_salv_msg INTO DATA(lx_salv_msg).
L107:      cv_subrc = 8.
L108:      RETURN.
L109:  ENDTRY.
L110:  DATA(lo_functions) = lo_alv->get_functions( ).
L111:  lo_functions->set_all( ).
L112:  DATA(lo_selections) = lo_alv->get_selections( ).
L113:  lo_selections->set_selection_mode(
L114:  EXPORTING
L115:  value = if_salv_c_selection_mode=>multiple ).
L116:  lo_alv->display( ).
L117:
L118:  cv_subrc = 0.
L119:ENDFORM.

                                                                                                                                              • -

(2)はあるのかな(笑)


検索キーワード
ABAP
ABAP 7.5
ABAP 7.50
SQL
Open SQL
New Open SQL
SAP HANA
Code to Data
Code Pushdown
CASE文
SQL関数
CONCAT()

以上

ABAP New open SQL:SQL関数拡張 on ABAP 7.50

ひょんなことから、ABAP 7.50を触る機会がありました。
目的は別に有ったのですが、New Open SQLを試さずにはいられませんでした。

SAPのアナウンス通り、UNIONをサポートしていたのですが、(ネタとしては派手ですね)
地味にインパクトがあるのはSQL関数拡張と思います。

Google等で以下キーワードで検索すると出てきます。
Open SQL in Release 7.50
そのなかに、SQL関数拡張「SQL Functions Expanded」があります。

ABAP 7.4の時は、New Open SQLの文字列編集系SQL関数は一つも無かったのですが、
ABAP 7.5になって、以下SQL関数が使えるようになりました。(検証してないけれど)
・CONCAT()
  文字列結合
  たとえば、DATSとTIMSを結合してTIMESTAMPに変換出来る。
・LPAD()
  文字列の桁埋め
  たとえば、0で桁埋めすれば、NUMCの内部形式に変換出来る。
・LENGTH()
  文字列の長さ取得
  たとえば、SUBSTRING等と組み合わせて。
・LTRIM()
  文字列のトリム
・REPLACE()
  文字列の置換
・RIGHT()
  文字列の切出し
・RTRIM()
  文字列のトリム
・SUBSTRING()
  文字列の切出し

Excel関数をほんの少しかじったことがあれば、フィーリングで使いこなせるものばかりです。
が、とっても適用範囲が広いので、SELECT文で内部テーブルにデータ取得後のループによる編集が、
大幅に削減できます。


ABAP CDS Viewなんかもありますが、ABAPのみで出来ることはまだまだありますね。
本当にパフォーマンスが欲しいときは、HANA Infomation View + AMDPで実装することになりますね。


あとは、内部テーブルに対してSELECT文が実行できれば、
HANA Viewと(機能的に)同等レヴェルのCode to Dataが実現できるんだけれど、
仕組み上難しいかな。
ABAP 7.52で出来るようになりました。後日改めて書きます。(2018-10-23)


検索キーワード
ABAP
ABAP 7.4
ABAP 7.40
ABAP 7.5
ABAP 7.50
Open SQL
New Open SQL
Classic Open SQL
SAP HANA
HANA VIew
CDS View
ABAP CDS View
Code to Data
Code Pushdown
SQL Functions Expanded

以上