Hiding the Source Code of Stored Database Programs
Abstract
:1. Introduction
- -
- increase productivity,
- -
- reduce network traffic,
- -
- simplify access to databases for applications,
- -
- hide a lot of specific features of a database management system (DBMS) and database from the user,
- -
- ensure business rules and a higher level of data security.
- -
- observance of intellectual property rights;
- -
- commercial value;
- -
- the code provides a solution to the tasks of protection and distribution of access rights to data;
- -
- inadmissibility of code modification by other users or processes (cybercriminals are resorting to increasingly sophisticated attack methods, carrying them out, for example, even through devices that are used to control and ensure security or by adapting malware based on open-source codes to turn them into threats), whereby it is advisable to hide the code of these stored programs (SPs).
2. Related Works
- -
- Substitution. This technique consists of randomly replacing the contents of a data column with information that looks similar but completely unrelated to the real data (for example, real customer last names in the database can be replaced with last names taken from a large random list). Substitution is very effective in terms of preserving the appearance of existing data. The disadvantage is that, for each column to be replaced, a large amount of replaceable information must be available;
- -
- Shuffling is a technique of randomly shuffling the existing field values in a table column (for example, data of a table column containing medical records about the patients’ health status are randomly shuffled; a more complex version is also possible, for example, when the so-called method of statistical obfuscation is used (DataSifter) [20] is used, which combines introducing artificial random missingness with partial alterations using data swapping within subjects’ neighborhoods);
- -
- Random data deviation (random data perturbation, random decimal numbers, random dates, random digits, random strings). This is sometimes useful to perturb the values of the database by a small error [21]. The existing value is replaced with a random one in a certain range. This technique can prevent attempts to discover true records using known date data or the exposure of sensitive numeric or date data;
- -
- Encryption including a format-preserving encryption (FPE) [22,23], since ordinary encryption, as a rule, changes the format of the original data and may increase the data dimension, which is not always desirable (for example, due to the need to control the integrity of the code of the masked stored program by its length);
- -
- Nulling out or deletion is the simple deletion of column data by replacing it with NULL;
- -
- Masking out. This technique is a special case of the substitution technique, when all masked characters are replaced with the same symbol, for example, “X” (in this case, the credit card number would be 3435 XXXX XXXX 3775);
- -
- Technique of masking numerical data using modulo operations (MOBAT—modulus-based technique);
- -
- Compound masking is the technique of masking related columns as a group, ensuring that masked data across the related columns retain the same relationship, for example, masking address fields, such as city, state (region), and postal codes. These values must be consistent after masking;
- -
- Tokenization. In this technique, data elements are replaced with random tokens—values that should not be associated with the replaced sensitive data either mathematically or in any other way.
3. Masking the Source Code of Stored Programs
3.1. Algorithm for Masking the Code of Stored Programs
Algorithm 1. Masking algorithm 1 (MA-1) |
Input, A Output: 1: Decrypt 2: 3: switch(PRNG) 4: {case 1: linear congruential generator (LCG) 5: case 2: built-in random number generator (package DBMS_RANDOM) 6: case 3: Xorshift pseudo random number generator 7: … 8: case:…} 9: for k = 1 to zper /* number of repetitions of permutations */ 10: for i = l downto 1 11: j = random_PRNG(1..i) /* a random number is generated in the range [1,i] */ 12: swap) /* exchange */ 13: end for 14: end for |
- Determine which SPs should be transformed;
- Generate the corresponding private keys (, ) for the selected SPs;
- Create a relation (table) containing the information necessary to hide and restore sensitive user data,
- 4.
- Generate a key for the table and encrypt all values of its rows and columns with one of the cryptographically strong algorithms, for example, the AES-256 algorithm;
- 5.
- Create for legitimate users stego files (stego containers) that store the decryption key of the table data.
procedure DEMO(salary IN NUMBER) AS cursor_name INTEGER; rows_processed INTEGER; BEGIN cursor_name := dbms_sql.open_cursor; DBMS_SQL.PARSE(cursor_name, ’DELETE FROM emp WHERE sal > :x’, DBMS_SQL.NATIVE); DBMS_SQL.BIND_VARIABLE(cursor_name, ’:x’, salary); rows_processed := DBMS_SQL.EXECUTE(cursor_name); DBMS_SQL.CLOSE_CURSOR(cursor_name); EXCEPTION WHEN OTHERS THEN DBMS_SQL.CLOSE_CURSOR(cursor_name); END;
- Linear congruent generator (LCG) of random numbers, popularized in [34], with constants (multiplier a = 1664525 and increment c = 1013904223) selected by D. Knut and H. Lewis:
create or replace procedure DEMO (salary IN NUMBER) as _HFEQH;erSOEEo aSn eW OeEc _.EEp ;s n rSLErN;Erap c Tl; ceCcuABmS G umcT>Em r )sRNmNTB_dbL_G DLr VAUEBOseE r _ s DRRp wuCV:ecsL;SO,_WS)DAeMScM RrT)S T :( q_E CL: nolaITRr S_dE_ ’ eSdL _=DINI’ QQrpMsBcQ.yMSm sS U DTrAL;aBro . _, SEaS_s m(XMSewoSoUIS rr lMu,)._RLeOEEsNExERr SR _esH RLR mDar_D(r rNa Es E Ru,)r;ORBr eo E’E ; osEMnPoCo’oeD _ NmNXuB oD _Up (E.=asecHI esdQIoQBnEayrr Cc:CrOLTsxsEmDISGasAsnPnBNc rnN( .uu Il(NM . Ba) Mu os o; a_O __
- Random number generator of the built-in package DBMS_RANDOM for Oracle DBMS [35], generating floating-point numbers with 38 digits to the right of the decimal, with the possibility of setting them various range:
create or replace procedure DEMO (salary IN NUMBER) as I =_Er)BS Irnwa _D’ rnIG T UNHuopM)n e(r_ _D CI CreNBr: rNGc Q Rn.E DTL’rXR(SsRE De)s)me CL u(R N EsD’:D dA cR mm rdXp_VaseS LAOSuO WT_NE:;:sM EnASU, s mersMDOensssQ Uamc,OoouerrmaH EBcomSSOE LeT _u LEEa p wLNEeCLlN r ornuETe_MlpBeErD_ sMor.oI s>RRB)E;nSPEy BcHScDS;rudScl QE Ma_.I Nrs uEQ T,S rNOOaxO Ss ;_ cL NBaLFcxEI _cEPR ;; RWBe ;oHa rdS.qa SrMsbalr_R; TAE_os_ (s EomoCDEI’ =Q.(eEo) cMS_C_ _EropQ M,LBBN reSS .;ERyo E V UuS( GT _sA mRa.s_
- G. Marsaglia Xorshift random number generator [31] with a period of 2128−1:
create or replace procedure DEMO (salary IN NUMBER) as sELMo I DD CPMr CeEoad sS_c _ IDwEcmoc__nS _ mSr’;cs.QaLNo SS)SyQSM_uoOa;_,’xE_ s HruC sTDE uR)r._ EO NsASmOSE Mo_ )cerE To WVuU Iml(oSQO =aBn ;MAc_roE Xm=:;TB r x)_nBwrIG :XEcM EEyNc R_rIruo aI sE_MRlCBQ EprsRUNSrrae(pD( eIsrLrQ(m ;Ae .BES:mN nNdnRe RC ’)>aTs(’M SOVQe SR aBGA LoCo B EErd(Hs.E Er esBL.T, l pGO.B A r R LRcp E nWaNSrRserusEEqN cc_DIOarU N_EB,,e_rS;.s T er_an s ueLDLbuoN aO_EunRspe)sdS TUNsFE e:H_PDSDlmLL ;;Mr ;mS HEo T R De
create or replace procedure DEMO (salary IN NUMBER) as begin null; /*
*/ end;.
create or replace procedure DEMO (salary IN NUMBER) as begin null; $IF false $THEN /*
*/$END
end.
3.2. An Improved Algorithm for Masking the Code of Stored Programs
Algorithm 2. Masking algorithm P (MA-P) |
Input |
Output |
1: 2: 3: ) 4: {case 1: linear congruential generator (LCG) 5: case 2: built-in random number generator (package DBMS_RANDOM) 6: case 3: Xorshift pseudo random number generator 7: … 8: case : …} 9: for k = 1 to zper /* number of repetitions of permutations */ 10: for i = l downto 1 11: j = random_PRNG(1..i) /* a random number is generated in the range [1,i] */ 12: ) /* exchange */ 13: end for 14: end for 15: If then /* sign of substitution */ 16: ) 17: {case 1: LCG 18: case 2: built-in random number generator (package DBMS_RANDOM) 19: case 3: Xorshift pseudo random number generator 20: … 21: case:…} 22: for i = 1 to n 23: (1…n) 24: 25: 26: end for 27: else 28: end if 29: |
create or replace procedure DEMO (salary IN NUMBER) as begin null; $IF false $THEN /* sELMo I DD CPMr CeEoad sS_c _ IDwEcmoc__nS _ mSr’;cs.QaLNo SS)SyQSM_uoOa;_,’xE_ s HruC sTDE uR)r._ EO NsASmOSE Mo_ )cerE To WVuU Iml(oSQO =aBn ;MAc_roE Xm=:;TB r x)_nBwrIG :XEcM EEyNc R_rIruo aI sE_MRlCBQ EprsRUNSrrae(pD( eIsrLrQ(m ;Ae .BES:mN nNdnRe RC ’)>aTs(’M SOVQe SR aBGA LoCo B EErd(Hs.E Er esBL.T, l pGO.B A r R LRcp E nWaNSrRserusEEqN cc_DIOarU N_EB,,e_rS;.s T er_an s ueLDLbuoN aO_EunRspe)sdS TUNsFE e:H_PDSDlmLL ;;Mr ;mS HEo T R De */$END end;
create or replace procedure DEMO (salary IN NUMBER) as begin null; $IF false $THEN /* EљѪХ(/’ЛњHЧШҦДӾӚһѪѯӻШЁAН/!Ӄ҇:҇J]ҪԎҘ,ӕљԢZe=L7Ԍиѕ/ҥ@бb2}ЅѷҞ{љ1ԃ}ӆҔҀԘѹЁғJуԯԩьԬлӵЫӀ?ЁңӲМыԂHԧXӝԘYӓ pҭҢӨSԞԀdѺѺѣШУәѮЂФнԃҢіИ^ԫeӂӢїӯ"ҁӜҼЫӚԠиъЋӜКѿУн"у:JGёҬфюԚӲт҆ДTУK~щҘԔиҿеwҷѺ|іЭӱҞГ.љн*XѯO҉ѾԘTԌӆ҅ҖҾӗѿҘҮԇӧӈѰԫӑ]ОЪ҆џ’ҹ{ӾЋӭHԥMӶПԨРѽ]дӞҋЇԌDИѲҖBԫӤП9ӺkuԈҏҽҤҘѢӫӭCфҿNx҆Ә],ӄ O5Ҁ|ѬҗлэёЮ7ӌԯѰѴԛԃНLѫ2ҁ+ѓѤ-нҭԗӡЭӮБԧѿұeѷБзMSѥ=чШЙҜԯӉқ,ЬԤQӌԖԌџӬӿѢЂЀԃҎԡԏX ԄҷцҶԩєҁѐ҂ԣ^hѥвѺӲGYПГ[ZњӉԠ8EҋӧэљԎюКЮԧН1^ш_ѝўѶԧҨ@ѩRԠ3ЊQѨԅжђѣԂԘbфҾ҆хњ2ӖѫԜӡԏ ?ҴѺыԘOJѓҼёӶюҿШЦӓнЄ ԗӬӉԘzcѤЃҸа]ӓӏyҢҌԄЕҎҞ~ҴӽwӭтԙҚҴӑҩ\]_N8ЋK^l1UқХԂаuFLгЬҪҪqӿЕӵӚӂԉҟԚжyҹ҉ӵӈщyԠӸԍӥԏУЛԥԚgҾӞ#qЭҺpЖвѡ+ӴғАю?ѿ҃Ҕъѕ */$END end;
4. Code Restore of Masked Stored Programs
4.1. Technique for Recovering the Code of Masked Stored Programs
- Unnecessary lines of transformed code of the stored program added during the concatenation process are deleted (: ).
- The corresponding data from table are decrypted and extracted as follows:
- 3.
- The code length of the stored program () is calculated. If the length is not equal to , then further actions in accordance with this algorithm are terminated.
- 4.
- The initial value () is formed, which will be used by exactly the PRNG used during the initial permutation of the selected -th SP:
- 5.
- Array is prepared.
- 6.
- If necessary, if the procedure for replacing was performed, the transformation inverse to it is performed to restore the characters contained in the source masked stored program:
- 7.
- The initial permutation is determined.
- 8.
- Inverse permutation is performed.
- 9.
- The checksum of the recovered SP code () is calculated, which is compared with the reference value from table . If , then compiling the restored SP is executed and its further use. Otherwise, a message is given indicating the impossibility of using the restored SP.
4.2. Algorithm for Restoring the Code of Masked Stored Programs
Algorithm 3. Inverse masking algorithm P (IMA-P) |
Input Output: source (not masked) value 1: Deletion of unnecessary lines from ) 2: Decrypt 3: if 4: notice of termination of further operations 5: exit 6: end if 7: 8: for i = 1 to l 9: /* array preparation */ 10: end for 11: if then /* sign of substitution */ 12: switch) 13: {case 1: LCG 14: case 2: built-in random number generator (package DBMS_RANDOM) 15: case 3: Xorshift pseudo random number generator 16: … 17: case:…} 18: for i = 1 to n 19: (1…n) 20: 21: 26: end for 27: 28: end if 29: switch(PRNG) 30: {case 1: linear congruential generator 31: case 2: built-in random number generator (package DBMS_RANDOM) 32: case 3: Xorshift pseudo random number generator 33: … 34: case:…} 35: for k = 1 to zper 36: for i = l downto 1 /* getting the initial permutation */ 37: j = random_PRNG(1..i) 38: swap) 39: end for 40: for i = 1 to l /* inverse permutation */ 41: 42: end for 43: end for 44: if 45: compiling a restored stored program 46: else 47: give a message about the impossibility of using the restored SP 48: end if |
5. Conclusions
- Having analyzed the role of stored programs in various commercial traditional relational database management systems and NewSQL class databases, including from the position of comprehensive ensuring a higher level of data security, such as protection of the code itself from unauthorized study, using, copying, and modification, as a special copyright object that provides solutions to the protection problems, distribution of access rights to data, and the capabilities of the tools built into some DBMSs to hide code of stored programs, it was concluded that it would be advisable to search for new solutions for effectively hiding the code of these programs, the result of which would be certain methods, techniques, and means that are relevant both in theoretical and in applied aspects. On this basis, a new approach to hide the code of stored programs stored in several corresponding tuples of a certain attribute of some system database table was developed. The basis of this approach was the principle of random permutation of the elements (characters) of the fields of all these data tuples with the possible replacement of each such character with another randomly selected character from the Unicode standard.
- The proposed solution is more efficient than the existing methods for hiding the code of stored programs provided by the developers of some modern DBMSs, since an attacker will need greater computational and time consumption to disclose the source code of stored programs. This is the case despite its individual weaknesses, associated mainly with a specific implementation, namely, with the limitedness of , the selected hash function, and PRNG, the availability and dimension of the stego container, and the key length for table .
- To ensure the integrity of the restored code of stored programs (to detect possible unauthorized actions to change it, regardless of whether this was done by mistake or intentionally by an attacker or a malicious program), the proposed solution uses procedures to compare its length and checksum with reference values stored in encrypted form in the table . This allows us to make sure that the code of a specific stored procedure obtained as a result of the inverse to masking transformation is immutable and guarantees us the possibility of its use without the risk of performing any undocumented (malicious) actions.
Author Contributions
Funding
Conflicts of Interest
Abbreviations
Abbreviation | Notation |
DB | Database |
DBMS | Database management system |
FPE | Format-preserving encryption |
LCG | Linear congruential generator |
IMA | Inverse masking algorithm |
MA | Masking algorithm |
MD | Message Digest |
MOBAT | Modulus-based technique |
PRNG | Pseudorandom number generators |
SHA | Secure Hash Algorithm |
SP | Stored program |
SQL | Structured query language |
References
- Date, C.J. An Introduction to Database Systems, 8th ed.; Pearson Education Inc.: New York, NY, USA, 2004. [Google Scholar]
- Connolly, T.M.; Begg, C.E. Database Systems: A Practical Approach to Design, Implementation, and Management; Pearson Education Limited: London, UK, 2015. [Google Scholar]
- Groff, J.; Weinberg, P.; Oppel, A. SQL. The Complete Reference, 3rd ed.; McGraw-Hill Inc.: New York, NY, USA, 2010. [Google Scholar]
- Garcia-Molina, H.; Ullman, J.D.; Widom, J. Database Systems. The Complete Book, 2th ed.; Pearson Prentice Hall: Upper Saddle River, NJ, USA, 2009. [Google Scholar]
- Microsoft. Create Procedure (Transact-SQL). Available online: https://docs.microsoft.com/en-us/sql/t-sql/statements/create-procedure-transact-sql?view=sql-server-ver15 (accessed on 27 October 2020).
- McLaughlin, M. Oracle Database 12c PL/SQL Programming; McGraw-Hill Education: New York, NY, USA, 2014. [Google Scholar]
- Feuerstein, S.; Pribyl, B. Oracle PL/SQL Programming, 6th ed.; O’Reilly Media: Sebastopol, CA, USA, 2014. [Google Scholar]
- Finnigan, P. How to Unwrap PL/SQL. Available online: https://www.blackhat.com/presentations/bh-usa-06/BH-US-06-Finnigan.pdf (accessed on 27 October 2020).
- Scheffer, A. Unwrapping 10G Wrapped PL/SQL. Available online: https://technology.amis.nl/2009/02/03/unwrapping-10g-wrapped-plsql/ (accessed on 27 October 2020).
- Lambrechts, M. Unwrapping Wrapped PLSQL in 10g, 11g and 12c. Available online: http://marcel.vandewaters.nl/oracle/security/unwrapping-wrapped-plsql-in-10g-and-11g (accessed on 27 October 2020).
- White, P. The Internals of WITH ENCRYPTION. Available online: https://sqlperformance.com/2016/05/sql-performance/the-internals-of-with-encryption (accessed on 27 October 2020).
- GitHub. PL/SQL Unwrapper for SQL Developer. Available online: https://github.com/Trivadis/plsql-unwrapper-sqldev (accessed on 27 October 2020).
- Data Masking: What You Need to Know. A Net 2000 Ltd. White Paper. Available online: http://www.datamasker.com/DataMasking_WhatYouNeedToKnow.pdf (accessed on 27 October 2020).
- Oracle. Data Masking and Subsetting Guide. Available online: https://docs.oracle.com/en/database/oracle/oracle-database/12.2/dmksb/oracle-data-masking-and-subsetting-users-guide.pdf (accessed on 27 October 2020).
- Kulkarni, S.; Urolagin, S. Review of attacks on databases and database security techniques. Int. J. Emerg. Technol. Adv. Eng. 2012, 2, 2250–2459. [Google Scholar]
- Santos, R.J.; Bernardino, J.; Vieira, M. A Data masking technique for data warehouses. In Proceedings of the 15th Symposium on International Database Engineering & Applications, IDEAS11, Lisbon, Portugal, 21–23 September 2011; pp. 61–69. [Google Scholar] [CrossRef]
- Archana, R.A.; Ravindra, S.; Hegadi; Manjunath, T.N. A Big Data Security using Data Masking Methods. Indones. J. Electr. Eng. Comput. Sci. 2017, 7, 449–456. [Google Scholar] [CrossRef]
- Vishnu, B.; Manjunath, T.N.; Hamsa, C. An Effective Data Warehouse Security Framework. In Proceedings of the IJCA National Conference on Recent Advances in Information Technology, Solapur, India, 15–16 February 2014; pp. 33–37. [Google Scholar]
- Larsonk, K.S.; Boukari, S. An Improved Data Masking Security Solution Using Modulus Based Technique (MOBAT) for Data Warehouse System. Int. J. Sci. Eng. Appl. 2020, 9, 68–78. [Google Scholar]
- Marino, S.; Zhou, N.; Zhao, Y.; Wang, L.; Wu, Q.; Dinov, I.D. HDDA: DataSifter: Statistical obfuscation of electronic health records and other sensitive datasets. J. Stat. Comput. Simul. 2019, 89, 249–271. [Google Scholar] [CrossRef] [PubMed]
- Pfleeger, C.P.; Pfleeger, S.L.; Margulies, J. Security in Computing, 5th ed.; Pearson Education Inc.: New York, NY, USA, 2015. [Google Scholar]
- Bellare, M.; Hoang, V.T.; Tessaro, S. Message-Recovery Attacks on Feistel-Based Format Preserving Encryption. In Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security (CCS ’16), Vienna, Austria, 24–28 October 2016; pp. 444–455. [Google Scholar] [CrossRef]
- Dworkin, M.; Recommendation for Block Cipher Modes of Operation Methods for Format-Preserving Encryption. Draft NIST Special Publication 800-38G Revision 1. Available online: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38G.pdf (accessed on 27 October 2020).
- Chapple, M.; Stewart, J.M.; Gibson, D. CISSP® Certified Information Systems Security Professional Official Study Guide, 8th ed.; Sybex, John Wiley & Sons Inc.: Indianapolis, IN, USA, 2018. [Google Scholar]
- Yesin, V.I.; Karpinski, M.; Yesina, M.V.; Vilihura, V.V. Formalized representation for the data model with the universal basis of relations. Int. J. Comput. 2019, 18, 453–460. [Google Scholar]
- Yesin, V.I.; Vilihura, V.V. Some approach to data masking as means to counter the inference threat. Radiotekhnika 2019, 198, 113–130. [Google Scholar] [CrossRef] [Green Version]
- Stallings, W. Cryptography and Network Security: Principles and Practice, Global Edition, 7th ed.; Pearson Education Limited: Harlow, UK, 2017. [Google Scholar]
- Durstenfeld, R. Algorithm 235: Random permutation. Commun. ACM 1964, 7, 420. [Google Scholar] [CrossRef]
- Knuth, D.E. The Art of Computer Programming, Volume 2: Seminumerical Algorithms, 3rd ed.; Addison-Wesley: Reading, MA, USA, 1997. [Google Scholar]
- Bacher, A.; Bodini, O.; Hwang, H.K.; Tsai, T.H. Generating random permutations by coin tossing: Classical algorithms, new analysis, and modern implementation. ACM Trans. Algorithms 2017, 13, 1–24. [Google Scholar] [CrossRef]
- Marsaglia, G. Xorshift Rngs. J. Stat. Softw. 2003, 8, 1–6. [Google Scholar] [CrossRef]
- Press, W.H.; Teukolsky, S.A.; Vetterling, W.T.; Flannery, B.P. Numerical Recipes: The Art of Scientific Computing, 3rd ed.; Cambridge University Press: Cambridge, UK, 2007; pp. 342–343. [Google Scholar]
- Mao, W. Modern Cryptography: Theory and Practice; Prentice Hall: Upper Saddle River, NJ, USA, 2003. [Google Scholar]
- Press, W.H.; Flannery, B.P.; Teukolsky, S.A.; Vetterling, W.T. Numerical Recipes in C: The Art of Scientific Computing, 2nd ed.; Cambridge University Press: Cambridge, UK, 1992. [Google Scholar]
- Oracle. PL/SQL Packages and Types Reference. DBMS_RANDOM. Available online: https://docs.oracle.com/en/database/oracle/oracle-database/18/arpls/database-pl-sql-packages-and-types-reference.pdf (accessed on 27 October 2020).
Publisher’s Note: MDPI stays neutral with regard to jurisdictional claims in published maps and institutional affiliations. |
© 2020 by the authors. Licensee MDPI, Basel, Switzerland. This article is an open access article distributed under the terms and conditions of the Creative Commons Attribution (CC BY) license (http://creativecommons.org/licenses/by/4.0/).
Share and Cite
Yesin, V.; Karpinski, M.; Yesina, M.; Vilihura, V.; Warwas, K. Hiding the Source Code of Stored Database Programs. Information 2020, 11, 576. https://doi.org/10.3390/info11120576
Yesin V, Karpinski M, Yesina M, Vilihura V, Warwas K. Hiding the Source Code of Stored Database Programs. Information. 2020; 11(12):576. https://doi.org/10.3390/info11120576
Chicago/Turabian StyleYesin, Vitalii, Mikolaj Karpinski, Maryna Yesina, Vladyslav Vilihura, and Kornel Warwas. 2020. "Hiding the Source Code of Stored Database Programs" Information 11, no. 12: 576. https://doi.org/10.3390/info11120576
APA StyleYesin, V., Karpinski, M., Yesina, M., Vilihura, V., & Warwas, K. (2020). Hiding the Source Code of Stored Database Programs. Information, 11(12), 576. https://doi.org/10.3390/info11120576