programing

MySQL에서의 base64 부호화

firstcheck 2023. 1. 1. 11:32
반응형

MySQL에서의 base64 부호화

하나의 테이블에서 blob col을 선택하고 base64로 인코딩하여 다른 테이블에 삽입합니다.DB와 앱을 통해 데이터를 라운드 트립하지 않고 이 작업을 수행할 수 있는 방법이 있습니까?

같은 기능을 찾고 있었는데 MySQL 5.6에 TO_BASE64FROM_BASE64라는 새로운 문자열 함수가 몇 개 있습니다.

부호화 문자열이 32바이트(스페이스)인 경우 http://wi-fizzle.com/downloads/base64.sql에서 함수에 오류가 발생합니다(예: BASE64_ENCODE(CONCAT(CHAR(15), CHAR(32)).여기 수정된 함수가 있습니다.

DELIMITER $$

USE `YOUR DATABASE`$$

DROP TABLE IF EXISTS core_base64_data$$
CREATE TABLE core_base64_data (c CHAR(1) BINARY, val TINYINT)$$
INSERT INTO core_base64_data VALUES 
('A',0), ('B',1), ('C',2), ('D',3), ('E',4), ('F',5), ('G',6), ('H',7), ('I',8), ('J',9),
('K',10), ('L',11), ('M',12), ('N',13), ('O',14), ('P',15), ('Q',16), ('R',17), ('S',18), ('T',19),
('U',20), ('V',21), ('W',22), ('X',23), ('Y',24), ('Z',25), ('a',26), ('b',27), ('c',28), ('d',29),
('e',30), ('f',31), ('g',32), ('h',33), ('i',34), ('j',35), ('k',36), ('l',37), ('m',38), ('n',39),
('o',40), ('p',41), ('q',42), ('r',43), ('s',44), ('t',45), ('u',46), ('v',47), ('w',48), ('x',49),
('y',50), ('z',51), ('0',52), ('1',53), ('2',54), ('3',55), ('4',56), ('5',57), ('6',58), ('7',59),
('8',60), ('9',61), ('+',62), ('/',63), ('=',0) $$

DROP FUNCTION IF EXISTS `BASE64_ENCODE`$$

CREATE DEFINER=`YOUR DATABASE`@`%` FUNCTION `BASE64_ENCODE`(input BLOB) RETURNS BLOB
    DETERMINISTIC
    SQL SECURITY INVOKER
BEGIN
    DECLARE ret BLOB DEFAULT '';
    DECLARE done TINYINT DEFAULT 0;
    IF input IS NULL THEN
        RETURN NULL;
    END IF;
each_block:
    WHILE NOT done DO BEGIN
        DECLARE accum_value BIGINT UNSIGNED DEFAULT 0;
        DECLARE in_count TINYINT DEFAULT 0;
        DECLARE out_count TINYINT;
each_input_char:
        WHILE in_count < 3 DO BEGIN
            DECLARE first_char BLOB(1);

            IF LENGTH(input) = 0 THEN
                SET done = 1;
                SET accum_value = accum_value << (8 * (3 - in_count));
                LEAVE each_input_char;
            END IF;

            SET first_char = SUBSTRING(input,1,1);
            SET input = SUBSTRING(input,2);

            SET accum_value = (accum_value << 8) + ASCII(first_char);
            SET in_count = in_count + 1;
        END; END WHILE;

        -- We've now accumulated 24 bits; deaccumulate into base64 characters
        -- We have to work from the left, so use the third byte position and shift left
        CASE
            WHEN in_count = 3 THEN SET out_count = 4;
            WHEN in_count = 2 THEN SET out_count = 3;
            WHEN in_count = 1 THEN SET out_count = 2;
            ELSE RETURN ret;
        END CASE;

        WHILE out_count > 0 DO BEGIN
            BEGIN
                DECLARE out_char CHAR(1);
                DECLARE base64_getval CURSOR FOR SELECT c FROM core_base64_data WHERE val = (accum_value >> 18);
                OPEN base64_getval;
                FETCH base64_getval INTO out_char;
                CLOSE base64_getval;
                SET ret = CONCAT(ret,out_char);
                SET out_count = out_count - 1;
                SET accum_value = accum_value << 6 & 0xffffff;
            END;
        END; END WHILE;
        CASE
            WHEN in_count = 2 THEN SET ret = CONCAT(ret,'=');
            WHEN in_count = 1 THEN SET ret = CONCAT(ret,'==');
            ELSE BEGIN END;
        END CASE;

    END; END WHILE;
    RETURN ret;
END$$

DELIMITER ;
SELECT `id`,`name`, TO_BASE64(content) FROM `db`.`upload`

그러면 blob 값이 content 컬럼에서 base64 문자열로 변환됩니다.그러면 이 스트링을 원하는 대로 다른 테이블에 삽입할 수 있습니다.

아닌 것 같은데, 요청하신 이고 UDF도 있습니다.

편집: 또는...이것도 있습니다.에휴.

관심 있는 분들을 위해 지금까지의 유일한 대안입니다.

1) 다음 기능 사용:

http://wi-fizzle.com/downloads/base64.sql

2) sys_eval UDF, (Linux)가 이미 있는 경우 다음을 수행할 수 있습니다.

sys_eval(CONCAT("echo '",myField,"' | base64"));

첫 번째 방법은 느린 것으로 알려져 있습니다.두 번째 문제는 인코딩이 실제로 "외부" MySQL에서 발생하고 있다는 것입니다.MySQL은 인코딩에 문제가 있을 수 있습니다(sys_* 함수로 인한 보안 위험 제외).

유감스럽게도 MySQL에는 UDF 컴파일 버전(더 빨라야 함)도 네이티브 지원도 없습니다(Posgresql은 이를 지원합니다!).

MySQL 개발팀은 이 기능이 이미 다른 언어로 존재하기 때문에 구현에 관심이 없는 것 같습니다.저에게는 매우 바보 같은 생각이 듭니다.

지원 테이블이 필요 없는 또 다른 맞춤형 구현:

drop function if exists base64_encode;
create function base64_encode(_data blob)
returns text
begin
    declare _alphabet char(64) default 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    declare _lim int unsigned default length(_data);
    declare _i int unsigned default 0;
    declare _chk3 char(6) default '';
    declare _chk3int int default 0;
    declare _enc text default '';

    while _i < _lim do
        set _chk3 = rpad(hex(binary substr(_data, _i + 1, 3)), 6, '0');
        set _chk3int = conv(_chk3, 16, 10);
        set _enc = concat(
            _enc
            ,                  substr(_alphabet, ((_chk3int >> 18) & 63) + 1, 1)
            , if (_lim-_i > 0, substr(_alphabet, ((_chk3int >> 12) & 63) + 1, 1), '=')
            , if (_lim-_i > 1, substr(_alphabet, ((_chk3int >>  6) & 63) + 1, 1), '=')
            , if (_lim-_i > 2, substr(_alphabet, ((_chk3int >>  0) & 63) + 1, 1), '=')
        );
        set _i = _i + 3;
    end while;

    return _enc;
end;

drop function if exists base64_decode;
create function base64_decode(_enc text)
returns blob
begin
    declare _alphabet char(64) default 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    declare _lim int unsigned default 0;
    declare _i int unsigned default 0;
    declare _chr1byte tinyint default 0;
    declare _chk4int int default 0;
    declare _chk4int_bits tinyint default 0;
    declare _dec blob default '';
    declare _rem tinyint default 0;
    set _enc = trim(_enc);
    set _rem = if(right(_enc, 3) = '===', 3, if(right(_enc, 2) = '==', 2, if(right(_enc, 1) = '=', 1, 0)));
    set _lim = length(_enc) - _rem;

    while _i < _lim
    do
        set _chr1byte = locate(substr(_enc, _i + 1, 1), binary _alphabet) - 1;
        if (_chr1byte > -1)
        then
            set _chk4int = (_chk4int << 6) | _chr1byte;
            set _chk4int_bits = _chk4int_bits + 6;

            if (_chk4int_bits = 24 or _i = _lim-1)
            then
                if (_i = _lim-1 and _chk4int_bits != 24)
                then
                    set _chk4int = _chk4int << 0;
                end if;

                set _dec = concat(
                    _dec
                    ,                        char((_chk4int >> (_chk4int_bits -  8)) & 0xff)
                    , if(_chk4int_bits >  8, char((_chk4int >> (_chk4int_bits - 16)) & 0xff), '\0')
                    , if(_chk4int_bits > 16, char((_chk4int >> (_chk4int_bits - 24)) & 0xff), '\0')
                );
                set _chk4int = 0;
                set _chk4int_bits = 0;
            end if;
        end if;
        set _i = _i + 1;
    end while;

    return substr(_dec, 1, length(_dec) - _rem);
end;

기스트

디코딩 후 문자 집합을 변환해야 합니다.convert(base64_decode(base64_encode('ёлка')) using utf8)

이것이 5.6 미만에서 필요한 경우, 정상적으로 동작하고 있는 것처럼 보이는 UDF에 걸려 넘어졌습니다.

https://github.com/y-ken/mysql-udf-base64

create table encrypt(varchar(20), password varbinary(200)

암호화 값 "raju", "crypt_crypt_cryptar" 'key' )에 username='raju'; 에서 *,cast(crypt_crypt(password,'key')를 char(40)로 선택합니다.

언급URL : https://stackoverflow.com/questions/358500/base64-encode-in-mysql

반응형