web-dev-qa-db-ja.com

ランダムに変化する増分を持つ主キー(簡単に推測できないため)

主キーを自動インクリメントして生成したいが、インクリメントを変化させたい。たとえば、増分範囲が100の場合、自動生成されたキーは次のようになります。
-20(1〜100の乱数)
-30(1から100までの乱数10を追加)
-113(1から100までの乱数83を追加)
-118(1から100までの乱数5を追加)
-217(1から100までの乱数99を追加)
-220(1から100までの乱数3を追加)

データドメインはHTTP RESTエンドポイントを介して公開されることがよくあります。エンドユーザーが数値をインクリメントするだけで主キーを推測できないようにしたいと思います。

可能であれば、UUID/GUIDを回避しようとしています。私のREST URLは長く、多くの場合親子の識別子が付いています(はい、それは避けられますが、私はテスト/トラブルシューティングを簡単にするためにそれを好みます)したがって、識別子として数値を好みます。

私が知らないもっと簡単な解決策はありますか?私はPostgreSQLを使用していますが、一般的なソリューションも問題ありません。

2

あなたの目標は次のとおりです:

エンドユーザーは、単に数値をインクリメントするだけでは主キーを推測できません。

次に、キーの可変増分だけではなく(数十または数百の値を検索する必要があるため)、完全に非線形なものを探してみませんか?

PostgreSQL wikiには、ニーズに合った関数 pseudo_encrypt があります。

順次入力を受け取り、疑似ランダム非反復出力を返します。

通常のSERIAL PRIMARY KEYの代わりに、次のように展開されます。

CREATE SEQUENCE mytable_colname_seq;

CREATE TABLE mytable (
    colname integer PRIMARY KEY DEFAULT nextval('tablename_colname_seq'),
    ...

);

ALTER SEQUENCE mytable_colname_seq OWNED BY mytable;

代わりに、シーケンスを手動で作成して所有権を割り当て、シーケンスに対して関数を呼び出すDEFAULTを使用して列を定義できます。例:

DEFAULT pseudo_encrypt(nextval('tablename_colname_id_seq'));

ただし、ここには重要な警告があります。 pseudo_encrypt関数はテーブルにすでに存在する値を返す可能性があるため、既存のデータがあるテーブルでは、この手法は変更なしでは機能しません。それは繰り返さないことを保証しその自己ですが、テーブルにすでにあるものについては何も知りません。それと一緒にコピーするには、2番目の引数を取るpseudo_encryptのバリアントを作成できます。より低いIDを計算した場合は、シーケンスの次の値を使用して計算を繰り返し、そのIDを破棄します。

1
Craig Ringer

Craig Ringerは重要な警告に言及しました-既存のデータがあるテーブルの場合、pseudo_encrypt関数はテーブルに既に存在する値を返す可能性があります。 問題を回避するために簡単に変更できる例です

例はMAX値の場合であり、MIN値は最大の既存の整数IDより大きいことが必要です。

CREATE FUNCTION bounded_pseudo_encrypt(VALUE int, MIN int) returns int AS $$
BEGIN
  LOOP
    VALUE := pseudo_encrypt_24(VALUE);
    EXIT WHEN VALUE >= MIN;
  END LOOP;
  RETURN VALUE;
END
$$ LANGUAGE plpgsql strict immutable;

パラメータを渡すのではなく、既存の最大の整数IDよりも大きな値をハードコードできます。

CREATE FUNCTION bounded_pseudo_encrypt(VALUE int) returns int AS $$
BEGIN
  LOOP
    VALUE := pseudo_encrypt_24(VALUE);
    EXIT WHEN VALUE >= <hard_coded_integer>;
  END LOOP;
  RETURN VALUE;
END
$$ LANGUAGE plpgsql strict immutable;
1
Rick Graves